MythTV  0.27pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
mythtv/programs/mythfrontend/main.cpp
Go to the documentation of this file.
1 #include <unistd.h>
2 #include <fcntl.h>
3 #include <signal.h>
4 #include <cerrno>
5 
6 #include <iostream>
7 using namespace std;
8 
9 #include <QFile>
10 #include <QFileInfo>
11 #include <QMap>
12 #include <QKeyEvent>
13 #include <QEvent>
14 #include <QDir>
15 #include <QTextCodec>
16 #include <QWidget>
17 #include <QApplication>
18 #include <QTimer>
19 
20 #include "previewgeneratorqueue.h"
21 #include "referencecounter.h"
22 #include "mythmiscutil.h"
23 #include "mythconfig.h"
24 #include "mythsystem.h"
25 #include "tv.h"
26 #include "proglist.h"
27 #include "progfind.h"
28 #include "scheduleeditor.h"
29 #include "manualschedule.h"
30 #include "playbackbox.h"
31 #include "themechooser.h"
32 #include "setupwizard_general.h"
33 #include "customedit.h"
34 #include "viewscheduled.h"
35 #include "programrecpriority.h"
36 #include "channelrecpriority.h"
37 #include "custompriority.h"
38 #include "audiooutput.h"
39 #include "globalsettings.h"
40 #include "audiogeneralsettings.h"
41 #include "grabbersettings.h"
42 #include "playgroup.h"
43 #include "networkcontrol.h"
44 #include "scheduledrecording.h"
45 #include "mythsystemevent.h"
46 #include "hardwareprofile.h"
47 #include "signalhandling.h"
48 
49 #include "compat.h" // For SIG* on MinGW
50 #include "exitcodes.h"
51 #include "exitprompt.h"
52 #include "programinfo.h"
53 #include "mythcontext.h"
54 #include "mythdbcon.h"
55 #include "guidegrid.h"
56 #include "mythplugin.h"
57 #include "remoteutil.h"
58 #include "dbcheck.h"
59 #include "mythmediamonitor.h"
60 #include "statusbox.h"
61 #include "idlescreen.h"
62 #include "lcddevice.h"
63 #include "langsettings.h"
64 #include "mythtranslation.h"
65 #include "commandlineparser.h"
66 #include "channelgroupsettings.h"
67 
68 #include "myththemedmenu.h"
69 #include "mediarenderer.h"
70 #include "mythmainwindow.h"
71 #include "mythcontrols.h"
72 #include "mythuihelper.h"
73 #include "mythdirs.h"
74 #include "mythdb.h"
76 #include "themechooser.h"
77 #include "mythversion.h"
78 #include "taskqueue.h"
79 
80 // Video
81 #include "cleanup.h"
82 #include "globals.h"
83 #include "videodlg.h"
84 #include "videoglobalsettings.h"
85 #include "videofileassoc.h"
86 #include "videoplayersettings.h"
87 #include "videometadatasettings.h"
88 #include "videolist.h"
89 
90 // DVD
91 #include "DVD/dvdringbuffer.h"
92 
93 // AirPlay
94 #ifdef USING_AIRPLAY
95 #include "AirPlay/mythraopdevice.h"
97 #endif
98 
99 #ifdef USING_LIBDNS_SD
100 #include <QScopedPointer>
101 #include "bonjourregister.h"
102 #endif
103 
104 static ExitPrompter *exitPopup = NULL;
106 
107 static QString logfile;
108 static MediaRenderer *g_pUPnp = NULL;
110 
111 static void handleExit(bool prompt);
112 static void resetAllKeys(void);
113 void handleSIGUSR1(void);
114 void handleSIGUSR2(void);
115 
116 
117 namespace
118 {
119  class RunSettingsCompletion : public QObject
120  {
121  Q_OBJECT
122 
123  public:
124  static void Create(bool check)
125  {
126  new RunSettingsCompletion(check);
127  }
128 
129  private:
130  RunSettingsCompletion(bool check)
131  {
132  if (check)
133  {
134  connect(&m_plcc,
135  SIGNAL(SigResultReady(bool, ParentalLevel::Level)),
136  SLOT(OnPasswordResultReady(bool,
139  }
140  else
141  {
142  OnPasswordResultReady(true, ParentalLevel::plHigh);
143  }
144  }
145 
146  ~RunSettingsCompletion() {}
147 
148  private slots:
149  void OnPasswordResultReady(bool passwordValid,
150  ParentalLevel::Level newLevel)
151  {
152  (void) newLevel;
153 
154  if (passwordValid)
155  {
156  VideoGeneralSettings settings;
157  settings.exec();
158  }
159  else
160  {
161  LOG(VB_GENERAL, LOG_WARNING,
162  QObject::tr("Aggressive Parental Controls Warning: "
163  "invalid password. An attempt to enter a "
164  "MythVideo settings screen was prevented."));
165  }
166 
167  deleteLater();
168  }
169 
170  public:
172  };
173 
174  class BookmarkDialog : MythScreenType
175  {
176  public:
177  BookmarkDialog(ProgramInfo *pginfo, MythScreenStack *parent) :
178  MythScreenType(parent, "bookmarkdialog"),
179  pgi(pginfo)
180  {
181  }
182 
183  bool Create()
184  {
185  QString msg = QObject::tr("DVD/Video contains a bookmark");
186  QString btn0msg = QObject::tr("Play from bookmark");
187  QString btn1msg = QObject::tr("Play from beginning");
188 
189  MythDialogBox *popup = new MythDialogBox(msg, GetScreenStack(), "bookmarkdialog");
190  if (!popup->Create())
191  {
192  delete popup;
193  return false;
194  }
195 
196  GetScreenStack()->AddScreen(popup);
197 
198  popup->SetReturnEvent(this, "bookmarkdialog");
199  popup->AddButton(btn0msg);
200  popup->AddButton(btn1msg);
201  return true;
202  }
203 
204  void customEvent(QEvent *event)
205  {
206  if (event->type() == DialogCompletionEvent::kEventType)
207  {
209  int buttonnum = dce->GetResult();
210 
211  if (dce->GetId() == "bookmarkdialog")
212  {
213  uint flags = kStartTVNoFlags;
214  if (buttonnum == 1)
215  {
216  flags |= kStartTVIgnoreBookmark;
217  }
218  else if (buttonnum != 0)
219  {
220  delete pgi;
221  return;
222  }
223 
224  TV::StartTV(pgi, flags);
225 
226  delete pgi;
227  }
228  }
229  }
230 
231  private:
232  ProgramInfo* pgi;
233  };
234 
235  void cleanup()
236  {
237 #ifdef USING_AIRPLAY
240 #endif
241 
242  delete exitPopup;
243  exitPopup = NULL;
244 
246 
247  if (g_pUPnp)
248  {
249  // This takes a few seconds, so inform the user:
250  LOG(VB_GENERAL, LOG_INFO, "Deleting UPnP client...");
251  delete g_pUPnp;
252  g_pUPnp = NULL;
253  }
254 
255  if (pmanager)
256  {
257  delete pmanager;
258  pmanager = NULL;
259  }
260 
262 
263  delete gContext;
264  gContext = NULL;
265 
267 
268  delete qApp;
269 
271  }
272 
273  class CleanupGuard
274  {
275  public:
276  typedef void (*CleanupFunc)();
277 
278  public:
279  CleanupGuard(CleanupFunc cleanFunction) :
280  m_cleanFunction(cleanFunction) {}
281 
282  ~CleanupGuard()
283  {
284  m_cleanFunction();
285  }
286 
287  private:
288  CleanupFunc m_cleanFunction;
289  };
290 }
291 
292 static void startAppearWiz(void)
293 {
294  int curX = gCoreContext->GetNumSetting("GuiOffsetX", 0);
295  int curY = gCoreContext->GetNumSetting("GuiOffsetY", 0);
296  int curW = gCoreContext->GetNumSetting("GuiWidth", 0);
297  int curH = gCoreContext->GetNumSetting("GuiHeight", 0);
298 
299  MythSystem *wizard = new MythSystem(
300  GetInstallPrefix() + "/bin/mythscreenwizard",
301  QStringList(),
303  wizard->Run();
304 
305  bool reload = false;
306 
307  if (!wizard->Wait())
308  {
309  // no reported errors, check for changed geometry parameters
310  gCoreContext->ClearSettingsCache("GuiOffsetX");
311  gCoreContext->ClearSettingsCache("GuiOffsetY");
312  gCoreContext->ClearSettingsCache("GuiWidth");
313  gCoreContext->ClearSettingsCache("GuiHeight");
314 
315  if ((curX != gCoreContext->GetNumSetting("GuiOffsetX", 0)) ||
316  (curY != gCoreContext->GetNumSetting("GuiOffsetY", 0)) ||
317  (curW != gCoreContext->GetNumSetting("GuiWidth", 0)) ||
318  (curH != gCoreContext->GetNumSetting("GuiHeight", 0)))
319  reload = true;
320  }
321 
322  delete wizard;
323  wizard = NULL;
324 
325  if (reload)
326  GetMythMainWindow()->JumpTo("Reload Theme");
327 }
328 
329 static void startKeysSetup()
330 {
332 
333  MythControls *mythcontrols = new MythControls(mainStack, "mythcontrols");
334 
335  if (mythcontrols->Create())
336  mainStack->AddScreen(mythcontrols);
337  else
338  delete mythcontrols;
339 }
340 
341 static void startGuide(void)
342 {
343  uint chanid = 0;
344  QString channum = gCoreContext->GetSetting("DefaultTVChannel");
345  channum = (channum.isEmpty()) ? "3" : channum;
346  QDateTime startTime;
347  GuideGrid::RunProgramGuide(chanid, channum, startTime, NULL, false, true, -2);
348 }
349 
350 static void startFinder(void)
351 {
353 }
354 
355 static void startSearchTitle(void)
356 {
358  ProgLister *pl = new ProgLister(mainStack, plTitleSearch, "", "");
359  if (pl->Create())
360  mainStack->AddScreen(pl);
361  else
362  delete pl;
363 }
364 
365 static void startSearchKeyword(void)
366 {
368  ProgLister *pl = new ProgLister(mainStack, plKeywordSearch, "", "");
369  if (pl->Create())
370  mainStack->AddScreen(pl);
371  else
372  delete pl;
373 }
374 
375 static void startSearchPeople(void)
376 {
378  ProgLister *pl = new ProgLister(mainStack, plPeopleSearch, "", "");
379  if (pl->Create())
380  mainStack->AddScreen(pl);
381  else
382  delete pl;
383 }
384 
385 static void startSearchPower(void)
386 {
388  ProgLister *pl = new ProgLister(mainStack, plPowerSearch, "", "");
389  if (pl->Create())
390  mainStack->AddScreen(pl);
391  else
392  delete pl;
393 }
394 
395 static void startSearchStored(void)
396 {
398  ProgLister *pl = new ProgLister(mainStack, plStoredSearch, "", "");
399  if (pl->Create())
400  mainStack->AddScreen(pl);
401  else
402  delete pl;
403 }
404 
405 static void startSearchChannel(void)
406 {
408  ProgLister *pl = new ProgLister(mainStack, plChannel, "", "");
409  if (pl->Create())
410  mainStack->AddScreen(pl);
411  else
412  delete pl;
413 }
414 
415 static void startSearchCategory(void)
416 {
418  ProgLister *pl = new ProgLister(mainStack, plCategory, "", "");
419  if (pl->Create())
420  mainStack->AddScreen(pl);
421  else
422  delete pl;
423 }
424 
425 static void startSearchMovie(void)
426 {
428  ProgLister *pl = new ProgLister(mainStack, plMovies, "", "");
429  if (pl->Create())
430  mainStack->AddScreen(pl);
431  else
432  delete pl;
433 }
434 
435 static void startSearchNew(void)
436 {
438  ProgLister *pl = new ProgLister(mainStack, plNewListings, "", "");
439  if (pl->Create())
440  mainStack->AddScreen(pl);
441  else
442  delete pl;
443 }
444 
445 static void startSearchTime(void)
446 {
448  ProgLister *pl = new ProgLister(mainStack, plTime, "", "");
449  if (pl->Create())
450  mainStack->AddScreen(pl);
451  else
452  delete pl;
453 }
454 
455 static void startManaged(void)
456 {
458 
459  ViewScheduled *viewsched = new ViewScheduled(mainStack);
460 
461  if (viewsched->Create())
462  mainStack->AddScreen(viewsched);
463  else
464  delete viewsched;
465 }
466 
467 static void startManageRecordingRules(void)
468 {
470 
471  ProgramRecPriority *progRecPrior = new ProgramRecPriority(mainStack,
472  "ManageRecRules");
473 
474  if (progRecPrior->Create())
475  mainStack->AddScreen(progRecPrior);
476  else
477  delete progRecPrior;
478 }
479 
480 static void startChannelRecPriorities(void)
481 {
483 
484  ChannelRecPriority *chanRecPrior = new ChannelRecPriority(mainStack);
485 
486  if (chanRecPrior->Create())
487  mainStack->AddScreen(chanRecPrior);
488  else
489  delete chanRecPrior;
490 }
491 
492 static void startCustomPriority(void)
493 {
495 
496  CustomPriority *custom = new CustomPriority(mainStack);
497 
498  if (custom->Create())
499  mainStack->AddScreen(custom);
500  else
501  delete custom;
502 }
503 
504 static void startPlaybackWithGroup(QString recGroup = "")
505 {
507 
508  PlaybackBox *pbb = new PlaybackBox(
509  mainStack, "playbackbox");
510 
511  if (pbb->Create())
512  {
513  if (!recGroup.isEmpty())
514  pbb->setInitialRecGroup(recGroup);
515 
516  mainStack->AddScreen(pbb);
517  }
518  else
519  delete pbb;
520 }
521 
522 static void startPlayback(void)
523 {
525 }
526 
527 static void startPrevious(void)
528 {
530  ProgLister *pl = new ProgLister(mainStack);
531  if (pl->Create())
532  mainStack->AddScreen(pl);
533  else
534  delete pl;
535 }
536 
537 static void startCustomEdit(void)
538 {
540  CustomEdit *custom = new CustomEdit(mainStack);
541 
542  if (custom->Create())
543  mainStack->AddScreen(custom);
544  else
545  delete custom;
546 }
547 
548 static void startManualSchedule(void)
549 {
551 
552  ManualSchedule *mansched= new ManualSchedule(mainStack);
553 
554  if (mansched->Create())
555  mainStack->AddScreen(mansched);
556  else
557  delete mansched;
558 }
559 
560 static bool isLiveTVAvailable(void)
561 {
562  if (RemoteGetFreeRecorderCount() > 0)
563  return true;
564 
565  QString msg = QObject::tr("All tuners are currently busy.");
566  if (TV::ConfiguredTunerCards() < 1)
567  msg = QObject::tr("There are no configured tuners.");
568 
569  ShowOkPopup(msg);
570  return false;
571 }
572 
573 static void startTVInGuide(void)
574 {
575  if (isLiveTVAvailable())
577 }
578 
579 static void startTVNormal(void)
580 {
581  if (isLiveTVAvailable())
583 }
584 
585 static void showStatus(void)
586 {
588 
589  StatusBox *statusbox = new StatusBox(mainStack);
590 
591  if (statusbox->Create())
592  mainStack->AddScreen(statusbox);
593  else
594  delete statusbox;
595 }
596 
597 
598 static void standbyScreen(void)
599 {
601 
602  IdleScreen *idlescreen = new IdleScreen(mainStack);
603 
604  if (idlescreen->Create())
605  mainStack->AddScreen(idlescreen);
606  else
607  delete idlescreen;
608 }
609 
610 static void RunVideoScreen(VideoDialog::DialogType type, bool fromJump = false)
611 {
612  QString message = QObject::tr("Loading videos ...");
613 
614  MythScreenStack *popupStack =
615  GetMythMainWindow()->GetStack("popup stack");
616 
617  MythUIBusyDialog *busyPopup = new MythUIBusyDialog(message,
618  popupStack, "mythvideobusydialog");
619 
620  if (busyPopup->Create())
621  popupStack->AddScreen(busyPopup, false);
622 
624 
625  VideoDialog::VideoListPtr video_list;
626  if (fromJump)
627  {
630  if (!saved.isNull())
631  {
632  video_list = saved->GetSaved();
633  }
634  }
635 
636  VideoDialog::BrowseType browse = static_cast<VideoDialog::BrowseType>(
637  gCoreContext->GetNumSetting("mythvideo.db_group_type",
639 
640  if (!video_list)
641  video_list = new VideoList;
642 
643  VideoDialog *mythvideo =
644  new VideoDialog(mainStack, "mythvideo", video_list, type, browse);
645 
646  if (mythvideo->Create())
647  {
648  busyPopup->Close();
649  mainStack->AddScreen(mythvideo);
650  }
651  else
652  busyPopup->Close();
653 }
654 
660 
661 static void playDisc()
662 {
663  //
664  // Get the command string to play a DVD
665  //
666 
667  bool isBD = false;
668 
669  QString command_string =
670  gCoreContext->GetSetting("mythdvd.DVDPlayerCommand");
671  QString bluray_mountpoint =
672  gCoreContext->GetSetting("BluRayMountpoint", "/media/cdrom");
673  QDir bdtest(bluray_mountpoint + "/BDMV");
674 
675  if (bdtest.exists())
676  isBD = true;
677 
678  if (isBD)
679  {
680  GetMythUI()->AddCurrentLocation("playdisc");
681 
682  QString filename = QString("bd:/%1").arg(bluray_mountpoint);
683 
684  GetMythMainWindow()->HandleMedia("Internal", filename, "", "", "", "",
685  0, 0, "", 0, "", "", true);
686 
688  }
689  else
690  {
691  QString dvd_device = MediaMonitor::defaultDVDdevice();
692 
693  if (dvd_device.isEmpty())
694  return; // User cancelled in the Popup
695 
696  GetMythUI()->AddCurrentLocation("playdisc");
697 
698  if ((command_string.indexOf("internal", 0, Qt::CaseInsensitive) > -1) ||
699  (command_string.length() < 1))
700  {
701 #ifdef Q_OS_MAC
702  // Convert a BSD 'leaf' name into a raw device path
703  QString filename = "dvd://dev/r"; // e.g. 'dvd://dev/rdisk2'
704 #elif USING_MINGW
705  QString filename = "dvd:"; // e.g. 'dvd:E\\'
706 #else
707  QString filename = "dvd:/"; // e.g. 'dvd://dev/sda'
708 #endif
709  filename += dvd_device;
710 
711  command_string = "Internal";
712  GetMythMainWindow()->HandleMedia(command_string, filename, "", "",
713  "", "", 0, 0, "", 0, "", "", true);
715 
716  return;
717  }
718  else
719  {
720  if (command_string.contains("%d"))
721  {
722  //
723  // Need to do device substitution
724  //
725  command_string =
726  command_string.replace(QRegExp("%d"), dvd_device);
727  }
730  myth_system(command_string);
731  sendPlaybackEnd();
733  if (GetMythMainWindow())
734  {
735  GetMythMainWindow()->raise();
736  GetMythMainWindow()->activateWindow();
737  if (GetMythMainWindow()->currentWidget())
738  GetMythMainWindow()->currentWidget()->setFocus();
739  }
740  }
742  }
743 }
744 
749 {
750  if (!dvd)
751  return;
752 
753  if (!dvd->isUsable()) // This isn't infallible, on some drives both a mount and libudf fail
754  return;
755 
756  switch (gCoreContext->GetNumSetting("DVDOnInsertDVD", 1))
757  {
758  case 0 : // Do nothing
759  break;
760  case 1 : // Display menu (mythdvd)*/
761  GetMythMainWindow()->JumpTo("Main Menu");
762  break;
763  case 2 : // play DVD or Blu-ray
764  GetMythMainWindow()->JumpTo("Main Menu");
765  playDisc();
766  break;
767  default:
768  LOG(VB_GENERAL, LOG_ERR,
769  "mythdvd main.o: handleMedia() does not know what to do");
770  }
771 }
772 
773 static void TVMenuCallback(void *data, QString &selection)
774 {
775  (void)data;
776  QString sel = selection.toLower();
777 
778  if (sel.startsWith("settings "))
779  {
780  GetMythUI()->AddCurrentLocation("Setup");
783  }
784 
785  if (sel == "tv_watch_live")
786  startTVNormal();
787  else if (sel == "tv_watch_live_epg")
788  startTVInGuide();
789  else if (sel.startsWith("tv_watch_recording"))
790  {
791  // use selection here because its case is untouched
792  if ((selection.length() > 19) && (selection.mid(18, 1) == " "))
793  startPlaybackWithGroup(selection.mid(19));
794  else
795  startPlayback();
796  }
797  else if (sel == "tv_schedule")
798  startGuide();
799  else if (sel == "tv_manualschedule")
801  else if (sel == "tv_custom_record")
802  startCustomEdit();
803  else if (sel == "tv_fix_conflicts")
804  startManaged();
805  else if (sel == "tv_manage_recording_rules")
807  else if (sel == "tv_progfind")
808  startFinder();
809  else if (sel == "tv_search_title")
811  else if (sel == "tv_search_keyword")
813  else if (sel == "tv_search_people")
815  else if (sel == "tv_search_power")
817  else if (sel == "tv_search_stored")
819  else if (sel == "tv_search_channel")
821  else if (sel == "tv_search_category")
823  else if (sel == "tv_search_movie")
825  else if (sel == "tv_search_new")
826  startSearchNew();
827  else if (sel == "tv_search_time")
828  startSearchTime();
829  else if (sel == "tv_previous")
830  startPrevious();
831  else if (sel == "settings appearance")
832  {
833  AppearanceSettings *settings = new AppearanceSettings();
834  DialogCode res = settings->exec();
835  delete settings;
836 
837  if (kDialogCodeRejected != res)
838  {
839  qApp->processEvents();
840  GetMythMainWindow()->JumpTo("Reload Theme");
841  }
842  }
843  else if (sel == "settings themechooser")
844  {
846  ThemeChooser *tp = new ThemeChooser(mainStack);
847 
848  if (tp->Create())
849  mainStack->AddScreen(tp);
850  else
851  delete tp;
852  }
853  else if (sel == "settings setupwizard")
854  {
856  GeneralSetupWizard *sw = new GeneralSetupWizard(mainStack, "setupwizard");
857 
858  if (sw->Create())
859  mainStack->AddScreen(sw);
860  else
861  delete sw;
862  }
863  else if (sel == "settings grabbers")
864  {
866  GrabberSettings *gs = new GrabberSettings(mainStack, "grabbersettings");
867 
868  if (gs->Create())
869  mainStack->AddScreen(gs);
870  else
871  delete gs;
872  }
873  else if (sel == "screensetupwizard")
874  {
875  startAppearWiz();
876  }
877  else if (sel == "setup_keys")
878  {
879  startKeysSetup();
880  }
881  else if (sel == "settings playgroup")
882  {
883  PlayGroupEditor editor;
884  editor.exec();
885  }
886  else if (sel == "settings general")
887  {
888  GeneralSettings settings;
889  settings.exec();
890  }
891  else if (sel == "settings audiogeneral")
892  {
893  AudioGeneralSettings audiosettings;
894  audiosettings.exec();
895  }
896  else if (sel == "settings maingeneral")
897  {
898  MainGeneralSettings mainsettings;
899  mainsettings.exec();
900  QStringList strlist( QString("REFRESH_BACKEND") );
902  }
903  else if (sel == "settings playback")
904  {
905  PlaybackSettings settings;
906  settings.exec();
907  }
908  else if (sel == "settings osd")
909  {
910  OSDSettings settings;
911  settings.exec();
912  }
913  else if (sel == "settings epg")
914  {
915  EPGSettings settings;
916  settings.exec();
917  }
918  else if (sel == "settings channelgroups")
919  {
920  ChannelGroupEditor editor;
921  editor.exec();
922  }
923  else if (sel == "settings generalrecpriorities")
924  {
926  settings.exec();
927  }
928  else if (sel == "settings channelrecpriorities")
929  {
931  }
932  else if (sel == "settings custompriority")
933  {
935  }
936  else if (sel == "system_events")
937  {
939 
941  mainStack, "System Event Editor");
942 
943  if (msee->Create())
944  mainStack->AddScreen(msee);
945  else
946  delete msee;
947  }
948  else if (sel == "video_settings_general")
949  {
950  RunSettingsCompletion::Create(gCoreContext->
951  GetNumSetting("VideoAggressivePC", 0));
952  }
953  else if (sel == "video_settings_player")
954  {
956 
957  PlayerSettings *ps = new PlayerSettings(mainStack, "player settings");
958 
959  if (ps->Create())
960  mainStack->AddScreen(ps);
961  }
962  else if (sel == "video_settings_metadata")
963  {
965 
966  MetadataSettings *ms = new MetadataSettings(mainStack, "metadata settings");
967 
968  if (ms->Create())
969  mainStack->AddScreen(ms);
970  }
971  else if (sel == "video_settings_associations")
972  {
974 
975  FileAssocDialog *fa = new FileAssocDialog(mainStack, "fa dialog");
976 
977  if (fa->Create())
978  mainStack->AddScreen(fa);
979  }
980  else if (sel == "manager")
982  else if (sel == "browser")
984  else if (sel == "listing")
986  else if (sel == "gallery")
988  else if (sel == "disc_play")
989  {
990  playDisc();
991  }
992  else if (sel == "tv_status")
993  showStatus();
994  else if (sel == "exiting_app_prompt")
995  handleExit(true);
996  else if (sel == "exiting_app")
997  handleExit(false);
998  else if (sel == "standby_mode")
999  standbyScreen();
1000  else
1001  LOG(VB_GENERAL, LOG_ERR, "Unknown menu action: " + selection);
1002 
1003  if (sel.startsWith("settings ") || sel == "video_settings_general")
1004  {
1006 
1008  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
1009 
1010  if (sel == "settings general" ||
1011  sel == "settings generalrecpriorities")
1012  ScheduledRecording::ReschedulePlace("TVMenuCallback");
1014  }
1015 }
1016 
1017 static void handleExit(bool prompt)
1018 {
1019  if (prompt)
1020  {
1021  if (!exitPopup)
1022  exitPopup = new ExitPrompter();
1023 
1024  exitPopup->handleExit();
1025  }
1026  else
1027  qApp->quit();
1028 }
1029 
1030 static bool RunMenu(QString themedir, QString themename)
1031 {
1032  QByteArray tmp = themedir.toLocal8Bit();
1033  menu = new MythThemedMenu(QString(tmp.constData()), "mainmenu.xml",
1034  GetMythMainWindow()->GetMainStack(), "mainmenu");
1035 
1036  if (menu->foundTheme())
1037  {
1038  LOG(VB_GENERAL, LOG_NOTICE, QString("Found mainmenu.xml for theme '%1'")
1039  .arg(themename));
1042  return true;
1043  }
1044 
1045  LOG(VB_GENERAL, LOG_ERR,
1046  QString("Couldn't find mainmenu.xml for theme '%1'") .arg(themename));
1047  delete menu;
1048  menu = NULL;
1049 
1050  return false;
1051 }
1052 
1053 // If any settings are missing from the database, this will write
1054 // the default values
1055 static void WriteDefaults()
1056 {
1057  PlaybackSettings ps;
1058  ps.Load();
1059  ps.Save();
1060  OSDSettings os;
1061  os.Load();
1062  os.Save();
1063  GeneralSettings gs;
1064  gs.Load();
1065  gs.Save();
1066  EPGSettings es;
1067  es.Load();
1068  es.Save();
1069  AppearanceSettings as;
1070  as.Load();
1071  as.Save();
1072  MainGeneralSettings mgs;
1073  mgs.Load();
1074  mgs.Save();
1076  grs.Load();
1077  grs.Save();
1079  vgs.Load();
1080  vgs.Save();
1081 }
1082 
1083 static int internal_play_media(const QString &mrl, const QString &plot,
1084  const QString &title, const QString &subtitle,
1085  const QString &director, int season, int episode,
1086  const QString &inetref, int lenMins, const QString &year,
1087  const QString &id, const bool useBookmark)
1088 {
1089  int res = -1;
1090 
1091  QFile checkFile(mrl);
1092  if ((!checkFile.exists() && !mrl.startsWith("dvd:")
1093  && !mrl.startsWith("bd:")
1094  && !mrl.startsWith("myth:")
1095  && !mrl.startsWith("http://")))
1096  {
1097  QString errorText = QObject::tr("Failed to open \n '%1' in %2 \n"
1098  "Check if the video exists")
1099  .arg(mrl.section('/', -1))
1100  .arg(mrl.section('/', 0, -2));
1101  ShowOkPopup(errorText);
1102  return res;
1103  }
1104 
1105  ProgramInfo *pginfo = new ProgramInfo(
1106  mrl, plot, title, subtitle, director, season, episode,
1107  inetref, lenMins, (year.toUInt()) ? year.toUInt() : 1900,
1108  id);
1109 
1110  pginfo->SetProgramInfoType(pginfo->DiscoverProgramInfoType());
1111 
1112  int64_t pos = 0;
1113 
1114  if (pginfo->IsVideoDVD())
1115  {
1116  DVDInfo *dvd = new DVDInfo(pginfo->GetPlaybackURL());
1117  if (dvd && dvd->IsValid())
1118  {
1119  QString name;
1120  QString serialid;
1121  if (dvd->GetNameAndSerialNum(name, serialid))
1122  {
1123  QStringList fields = pginfo->QueryDVDBookmark(serialid);
1124  if (!fields.empty())
1125  {
1126  QStringList::Iterator it = fields.begin();
1127  pos = (int64_t)((*++it).toLongLong() & 0xffffffffLL);
1128  }
1129  }
1130  }
1131  else
1132  {
1133  if (dvd)
1134  delete dvd;
1135  delete pginfo;
1136  return res;
1137  }
1138  delete dvd;
1139  }
1140  else if (pginfo->IsVideo())
1141  pos = pginfo->QueryBookmark();
1142 
1143  if (useBookmark && pos > 0)
1144  {
1146  BookmarkDialog *bookmarkdialog = new BookmarkDialog(pginfo, mainStack);
1147  if (!bookmarkdialog->Create())
1148  {
1149  delete bookmarkdialog;
1150  delete pginfo;
1151  return res;
1152  }
1153  }
1154  else
1155  {
1157 
1158  res = 0;
1159 
1160  delete pginfo;
1161  }
1162 
1163  return res;
1164 }
1165 
1166 static void gotoMainMenu(void)
1167 {
1168  // Reset the selected button to the first item.
1169  MythThemedMenuState *menu = dynamic_cast<MythThemedMenuState *>
1171  if (menu)
1172  menu->m_buttonList->SetItemCurrent(0);
1173 }
1174 
1175 // If the theme specified in the DB is somehow broken, try a standard one:
1176 //
1177 static bool resetTheme(QString themedir, const QString badtheme)
1178 {
1179  QString themename = DEFAULT_UI_THEME;
1180 
1181  if (badtheme == DEFAULT_UI_THEME)
1182  themename = FALLBACK_UI_THEME;
1183 
1184  LOG(VB_GENERAL, LOG_WARNING,
1185  QString("Overriding broken theme '%1' with '%2'")
1186  .arg(badtheme).arg(themename));
1187 
1188  gCoreContext->OverrideSettingForSession("Theme", themename);
1189  themedir = GetMythUI()->FindThemeDir(themename);
1190 
1193  GetMythUI()->LoadQtConfig();
1194 #if CONFIG_DARWIN
1195  GetMythMainWindow()->Init(OPENGL_PAINTER);
1196 #else
1197  GetMythMainWindow()->Init();
1198 #endif
1199 
1201 
1202  return RunMenu(themedir, themename);
1203 }
1204 
1205 static int reloadTheme(void)
1206 {
1207  QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
1208  QString themedir = GetMythUI()->FindThemeDir(themename);
1209  if (themedir.isEmpty())
1210  {
1211  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
1212  .arg(themename));
1213  return GENERIC_EXIT_NO_THEME;
1214  }
1215 
1218 
1220 
1221  GetMythUI()->LoadQtConfig();
1222 
1223  if (menu)
1224  {
1225  menu->Close();
1226  }
1227 #if CONFIG_DARWIN
1228  GetMythMainWindow()->Init(OPENGL_PAINTER);
1229 #else
1230  GetMythMainWindow()->Init();
1231 #endif
1232 
1234 
1236 
1237  if (!RunMenu(themedir, themename) && !resetTheme(themedir, themename))
1238  return GENERIC_EXIT_NO_THEME;
1239 
1240  LCD::SetupLCD();
1241  if (LCD *lcd = LCD::Get())
1242  {
1243  lcd->setupLEDs(RemoteGetRecordingMask);
1244  lcd->resetServer();
1245  }
1246 
1247  return 0;
1248 }
1249 
1250 static void reloadTheme_void(void)
1251 {
1252  int err = reloadTheme();
1253  if (err)
1254  exit(err);
1255 }
1256 
1257 static void setDebugShowBorders(void)
1258 {
1260  p->SetDebugMode(!p->ShowBorders(), p->ShowTypeNames());
1261 
1264 }
1265 
1266 static void setDebugShowNames(void)
1267 {
1269  p->SetDebugMode(p->ShowBorders(), !p->ShowTypeNames());
1270 
1273 }
1274 
1275 static void InitJumpPoints(void)
1276 {
1277  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Reload Theme"),
1278  "", "", reloadTheme_void);
1279  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Main Menu"),
1280  "", "", gotoMainMenu);
1281  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Program Guide"),
1282  "", "", startGuide, "GUIDE");
1283  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Program Finder"),
1284  "", "", startFinder, "FINDER");
1285  //REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Search Listings"),
1286  // "", "", startSearch);
1287  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Manage Recordings / "
1288  "Fix Conflicts"), "", "", startManaged, "VIEWSCHEDULED");
1289  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Manage Recording Rules"),
1290  "", "", startManageRecordingRules);
1291  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Channel Recording "
1292  "Priorities"), "", "", startChannelRecPriorities);
1293  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "TV Recording Playback"),
1294  "", "", startPlayback, "JUMPREC");
1295  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Live TV"),
1296  "", "", startTVNormal);
1297  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Live TV In Guide"),
1298  "", "", startTVInGuide);
1299  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Status Screen"),
1300  "", "", showStatus);
1301  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Previously Recorded"),
1302  "", "", startPrevious);
1303 
1304  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Standby Mode"),
1305  "", "", standbyScreen);
1306 
1307  // Video
1308 
1309  REG_JUMP(JUMP_VIDEO_DEFAULT, QT_TRANSLATE_NOOP("MythControls",
1310  "The Video Default View"), "", jumpScreenVideoDefault);
1311  REG_JUMP(JUMP_VIDEO_MANAGER, QT_TRANSLATE_NOOP("MythControls",
1312  "The Video Manager"), "", jumpScreenVideoManager);
1313  REG_JUMP(JUMP_VIDEO_BROWSER, QT_TRANSLATE_NOOP("MythControls",
1314  "The Video Browser"), "", jumpScreenVideoBrowser);
1315  REG_JUMP(JUMP_VIDEO_TREE, QT_TRANSLATE_NOOP("MythControls",
1316  "The Video Listings"), "", jumpScreenVideoTree);
1317  REG_JUMP(JUMP_VIDEO_GALLERY, QT_TRANSLATE_NOOP("MythControls",
1318  "The Video Gallery"), "", jumpScreenVideoGallery);
1319  REG_JUMP("Play Disc", QT_TRANSLATE_NOOP("MythControls",
1320  "Play an Optical Disc"), "", playDisc);
1321 
1322  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Toggle Show Widget Borders"),
1323  "", "", setDebugShowBorders, false);
1324  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Toggle Show Widget Names"),
1325  "", "", setDebugShowNames, false);
1326  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Reset All Keys"),
1327  QT_TRANSLATE_NOOP("MythControls", "Reset all keys to defaults"),
1328  "", resetAllKeys, false);
1329 }
1330 
1331 static void ReloadJumpPoints(void)
1332 {
1333  MythMainWindow *mainWindow = GetMythMainWindow();
1334  mainWindow->ClearAllJumps();
1335  InitJumpPoints();
1336 }
1337 
1338 static void InitKeys(void)
1339 {
1340  REG_KEY("Video","PLAYALT", QT_TRANSLATE_NOOP("MythControls",
1341  "Play selected item in alternate player"), "ALT+P");
1342  REG_KEY("Video","FILTER", QT_TRANSLATE_NOOP("MythControls",
1343  "Open video filter dialog"), "F");
1344  REG_KEY("Video","BROWSE", QT_TRANSLATE_NOOP("MythControls",
1345  "Change browsable in video manager"), "B");
1346  REG_KEY("Video","INCPARENT", QT_TRANSLATE_NOOP("MythControls",
1347  "Increase Parental Level"), "],},F11");
1348  REG_KEY("Video","DECPARENT", QT_TRANSLATE_NOOP("MythControls",
1349  "Decrease Parental Level"), "[,{,F10");
1350  REG_KEY("Video","INCSEARCH", QT_TRANSLATE_NOOP("MythControls",
1351  "Show Incremental Search Dialog"), "Ctrl+S");
1352  REG_KEY("Video","DOWNLOADDATA", QT_TRANSLATE_NOOP("MythControls",
1353  "Download metadata for current item"), "W");
1354  REG_KEY("Video","ITEMDETAIL", QT_TRANSLATE_NOOP("MythControls",
1355  "Display Item Detail Popup"), "");
1356  REG_KEY("Video","HOME", QT_TRANSLATE_NOOP("MythControls",
1357  "Go to the first video"), "Home");
1358  REG_KEY("Video","END", QT_TRANSLATE_NOOP("MythControls",
1359  "Go to the last video"), "End");
1360 }
1361 
1362 static void ReloadKeys(void)
1363 {
1364  GetMythMainWindow()->ClearKeyContext("Video");
1365  InitKeys();
1366 
1367  TV::ReloadKeys();
1368 }
1369 
1370 static void SetFuncPtrs(void)
1371 {
1372  TV::SetFuncPtr("playbackbox", (void *)PlaybackBox::RunPlaybackBox);
1373  TV::SetFuncPtr("viewscheduled", (void *)ViewScheduled::RunViewScheduled);
1374  TV::SetFuncPtr("programguide", (void *)GuideGrid::RunProgramGuide);
1375  TV::SetFuncPtr("programfinder", (void *)RunProgramFinder);
1376  TV::SetFuncPtr("scheduleeditor", (void *)ScheduleEditor::RunScheduleEditor);
1377 }
1378 
1382 static void clearAllKeys(void)
1383 {
1384  MSqlQuery query(MSqlQuery::InitCon());
1385 
1386  query.prepare("DELETE FROM keybindings "
1387  "WHERE hostname = :HOSTNAME;");
1388  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1389  if (!query.exec())
1390  MythDB::DBError("Deleting keybindings", query);
1391  query.prepare("DELETE FROM jumppoints "
1392  "WHERE hostname = :HOSTNAME;");
1393  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1394  if (!query.exec())
1395  MythDB::DBError("Deleting jumppoints", query);
1396 }
1397 
1401 static void resetAllKeys(void)
1402 {
1403  clearAllKeys();
1404  // Reload MythMainWindow bindings
1406  // Reload Jump Points
1407  ReloadJumpPoints();
1408  // Reload mythfrontend and TV bindings
1409  ReloadKeys();
1410 }
1411 
1413 {
1414  REG_MEDIAPLAYER("Internal", QT_TRANSLATE_NOOP("MythControls",
1415  "MythTV's native media player."), internal_play_media);
1416  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1417  "MythDVD DVD Media Handler"), "", "", handleDVDMedia,
1418  MEDIATYPE_DVD, QString::null);
1419  return 0;
1420 }
1421 
1422 static void CleanupMyOldInUsePrograms(void)
1423 {
1424  MSqlQuery query(MSqlQuery::InitCon());
1425 
1426  query.prepare("DELETE FROM inuseprograms "
1427  "WHERE hostname = :HOSTNAME and recusage = 'player' ;");
1428  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1429  if (!query.exec())
1430  MythDB::DBError("CleanupMyOldInUsePrograms", query);
1431 }
1432 
1433 int main(int argc, char **argv)
1434 {
1435  bool bPromptForBackend = false;
1436  bool bBypassAutoDiscovery = false;
1437 
1439  if (!cmdline.Parse(argc, argv))
1440  {
1441  cmdline.PrintHelp();
1442  return GENERIC_EXIT_INVALID_CMDLINE;
1443  }
1444 
1445  if (cmdline.toBool("showhelp"))
1446  {
1447  cmdline.PrintHelp();
1448  return GENERIC_EXIT_OK;
1449  }
1450 
1451  if (cmdline.toBool("showversion"))
1452  {
1453  cmdline.PrintVersion();
1454  return GENERIC_EXIT_OK;
1455  }
1456 
1457  CleanupGuard callCleanup(cleanup);
1458 
1459 #ifdef Q_OS_MAC
1460  // Without this, we can't set focus to any of the CheckBoxSetting, and most
1461  // of the MythPushButton widgets, and they don't use the themed background.
1462  QApplication::setDesktopSettingsAware(false);
1463 #endif
1464  new QApplication(argc, argv);
1465  QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHFRONTEND);
1466 
1467 #ifndef _WIN32
1468  QList<int> signallist;
1469  signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
1470  << SIGILL;
1471 #if ! CONFIG_DARWIN
1472  signallist << SIGRTMIN;
1473 #endif
1474  SignalHandler::Init(signallist);
1477  signal(SIGHUP, SIG_IGN);
1478 #endif
1479 
1480  int retval;
1481  if ((retval = cmdline.ConfigureLogging()) != GENERIC_EXIT_OK)
1482  return retval;
1483 
1484  bool ResetSettings = false;
1485 
1486  if (cmdline.toBool("prompt"))
1487  bPromptForBackend = true;
1488  if (cmdline.toBool("noautodiscovery"))
1489  bBypassAutoDiscovery = true;
1490 
1491  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
1492  cerr << "Unable to ignore SIGPIPE\n";
1493 
1494  if (!cmdline.toString("display").isEmpty())
1495  {
1496  MythUIHelper::SetX11Display(cmdline.toString("display"));
1497  }
1498 
1499  if (!cmdline.toString("geometry").isEmpty())
1500  {
1501  MythUIHelper::ParseGeometryOverride(cmdline.toString("geometry"));
1502  }
1503 
1504  gContext = new MythContext(MYTH_BINARY_VERSION);
1505 
1506  if (!gContext->Init(true, bPromptForBackend, bBypassAutoDiscovery))
1507  {
1508  LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
1509  return GENERIC_EXIT_NO_MYTHCONTEXT;
1510  }
1511 
1512  cmdline.ApplySettingsOverride();
1513 
1514  if (!GetMythDB()->HaveSchema())
1515  {
1516  if (!InitializeMythSchema())
1517  return GENERIC_EXIT_DB_ERROR;
1518  }
1519 
1520  if (cmdline.toBool("reset"))
1521  ResetSettings = true;
1522 
1523  if (!cmdline.toBool("noupnp"))
1524  {
1525  g_pUPnp = new MediaRenderer();
1526  if (!g_pUPnp->initialized())
1527  {
1528  delete g_pUPnp;
1529  g_pUPnp = NULL;
1530  }
1531  }
1532 
1533  QString fileprefix = GetConfDir();
1534 
1535  QDir dir(fileprefix);
1536  if (!dir.exists())
1537  dir.mkdir(fileprefix);
1538 
1539  if (ResetSettings)
1540  {
1541  AppearanceSettings as;
1542  as.Save();
1543 
1544  gCoreContext->SaveSetting("Theme", DEFAULT_UI_THEME);
1545  gCoreContext->SaveSetting("Language", "");
1546  gCoreContext->SaveSetting("Country", "");
1547 
1548  return GENERIC_EXIT_OK;
1549  }
1550 
1551  setuid(getuid());
1552 
1553 #ifdef USING_LIBDNS_SD
1554  // this needs to come after gCoreContext has been initialised
1555  // (for hostname) - hence it is not in MediaRenderer
1556  QScopedPointer<BonjourRegister> bonjour(new BonjourRegister());
1557  if (bonjour.data())
1558  {
1559  QByteArray dummy;
1560  int port = gCoreContext->GetNumSetting("UPnP/MythFrontend/ServicePort", 6547);
1561  QByteArray name("Mythfrontend on ");
1562  name.append(gCoreContext->GetHostName());
1563  bonjour->Register(port, "_mythfrontend._tcp",
1564  name, dummy);
1565  }
1566 #endif
1567 
1568 #ifdef USING_AIRPLAY
1569  if (gCoreContext->GetNumSetting("AirPlayEnabled", true))
1570  {
1572  if (!gCoreContext->GetNumSetting("AirPlayAudioOnly", false))
1573  {
1575  }
1576  }
1577 #endif
1578 
1579  LCD::SetupLCD();
1580  if (LCD *lcd = LCD::Get())
1581  lcd->setupLEDs(RemoteGetRecordingMask);
1582 
1583  MythTranslation::load("mythfrontend");
1584 
1585  QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
1586 
1587  QString themedir = GetMythUI()->FindThemeDir(themename);
1588  if (themedir.isEmpty())
1589  {
1590  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
1591  .arg(themename));
1592  return GENERIC_EXIT_NO_THEME;
1593  }
1594 
1595  GetMythUI()->LoadQtConfig();
1596 
1597  themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
1598  themedir = GetMythUI()->FindThemeDir(themename);
1599  if (themedir.isEmpty())
1600  {
1601  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
1602  .arg(themename));
1603  return GENERIC_EXIT_NO_THEME;
1604  }
1605 
1606  MythMainWindow *mainWindow = GetMythMainWindow();
1607 #if CONFIG_DARWIN
1608  mainWindow->Init(OPENGL_PAINTER);
1609 #else
1610  mainWindow->Init();
1611 #endif
1612  mainWindow->setWindowTitle(QObject::tr("MythTV Frontend"));
1613 
1614  // We must reload the translation after a language change and this
1615  // also means clearing the cached/loaded theme strings, so reload the
1616  // theme which also triggers a translation reload
1618  {
1619  if (!reloadTheme())
1620  return GENERIC_EXIT_NO_THEME;
1621  }
1622 
1623  if (!UpgradeTVDatabaseSchema(false))
1624  {
1625  LOG(VB_GENERAL, LOG_ERR,
1626  "Couldn't upgrade database to new schema, exiting.");
1627  return GENERIC_EXIT_DB_OUTOFDATE;
1628  }
1629 
1630  WriteDefaults();
1631 
1632  // Refresh Global/Main Menu keys after DB update in case there was no DB
1633  // when they were written originally
1634  mainWindow->ReloadKeys();
1635 
1636  InitJumpPoints();
1637  InitKeys();
1638  TV::InitKeys();
1639  SetFuncPtrs();
1640 
1642 
1644 
1645  setHttpProxy();
1646 
1647  pmanager = new MythPluginManager();
1649 
1651  if (mon)
1652  {
1653  mon->StartMonitoring();
1654  mainWindow->installEventFilter(mon);
1655  }
1656 
1657  NetworkControl *networkControl = NULL;
1658  if (gCoreContext->GetNumSetting("NetworkControlEnabled", 0))
1659  {
1660  int port = gCoreContext->GetNumSetting("NetworkControlPort", 6546);
1661  networkControl = new NetworkControl();
1662  if (!networkControl->listen(port))
1663  LOG(VB_GENERAL, LOG_ERR,
1664  QString("NetworkControl failed to bind to port %1.")
1665  .arg(port));
1666  }
1667 
1668 #ifdef __linux__
1669 #ifdef CONFIG_BINDINGS_PYTHON
1671  if (profile && profile->NeedsUpdate())
1672  profile->SubmitProfile();
1673  delete profile;
1674 #endif
1675 #endif
1676 
1677  if (!RunMenu(themedir, themename) && !resetTheme(themedir, themename))
1678  {
1679  return GENERIC_EXIT_NO_THEME;
1680  }
1681 
1682  ThemeUpdateChecker *themeUpdateChecker = NULL;
1683  if (gCoreContext->GetNumSetting("ThemeUpdateNofications", 1))
1684  themeUpdateChecker = new ThemeUpdateChecker();
1685 
1686  MythSystemEventHandler *sysEventHandler = new MythSystemEventHandler();
1687 
1689 
1691  PreviewGenerator::kRemote, 50, 60);
1692 
1693  if (cmdline.toBool("runplugin"))
1694  {
1695  QStringList plugins = pmanager->EnumeratePlugins();
1696 
1697  if (plugins.contains(cmdline.toString("runplugin")))
1698  pmanager->run_plugin(cmdline.toString("runplugin"));
1699  else if (plugins.contains("myth" + cmdline.toString("runplugin")))
1700  pmanager->run_plugin("myth" + cmdline.toString("runplugin"));
1701  else
1702  {
1703  LOG(VB_GENERAL, LOG_ERR,
1704  QString("Invalid plugin name supplied on command line: '%1'")
1705  .arg(cmdline.toString("runplugin")));
1706  LOG(VB_GENERAL, LOG_ERR,
1707  QString("Available plugins: %1")
1708  .arg(plugins.join(", ")));
1709  return GENERIC_EXIT_INVALID_CMDLINE;
1710  }
1711  }
1712  else if (cmdline.toBool("jumppoint"))
1713  {
1715 
1716  if (mmw->DestinationExists(cmdline.toString("jumppoint")))
1717  mmw->JumpTo(cmdline.toString("jumppoint"));
1718  else
1719  {
1720  LOG(VB_GENERAL, LOG_ERR,
1721  QString("Invalid jump point supplied on the command line: %1")
1722  .arg(cmdline.toString("jumppoint")));
1723  LOG(VB_GENERAL, LOG_ERR,
1724  QString("Available jump points: %2")
1725  .arg(mmw->EnumerateDestinations().join(", ")));
1726  return GENERIC_EXIT_INVALID_CMDLINE;
1727  }
1728  }
1729 
1730  int ret = qApp->exec();
1731 
1733 
1734  if (themeUpdateChecker)
1735  delete themeUpdateChecker;
1736 
1737  delete sysEventHandler;
1738 
1740 
1741  if (mon)
1742  mon->deleteLater();
1743 
1744  delete networkControl;
1745 
1746  return ret;
1747 
1748 }
1749 
1750 void handleSIGUSR1(void)
1751 {
1752  LOG(VB_GENERAL, LOG_INFO, "Reloading theme");
1753  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
1755  GetMythMainWindow()->JumpTo("Reload Theme");
1757 }
1758 
1759 void handleSIGUSR2(void)
1760 {
1761  LOG(VB_GENERAL, LOG_INFO, "Restarting LIRC handler");
1763 }
1764 
1765 #include "main.moc"
1766 /* vim: set expandtab tabstop=4 shiftwidth=4: */