MythTV  master
osd.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QCoreApplication>
3 
4 // libmyth
5 #include "mythlogging.h"
6 
7 // libmythui
8 #include "mythmainwindow.h"
9 #include "mythuihelper.h"
10 #include "mythpainter.h"
11 #include "mythuiimage.h"
12 #include "mythuiprogressbar.h"
13 #include "mythdialogbox.h"
14 #include "mythuitext.h"
15 #include "mythuibutton.h"
16 #include "mythuieditbar.h"
17 #include "mythuistatetype.h"
18 #include "mythuigroup.h"
19 
20 // libmythtv
21 #include "channelutil.h"
22 #include "teletextscreen.h"
23 #include "subtitlescreen.h"
24 #include "interactivescreen.h"
25 #include "osd.h"
26 #include "Bluray/bdringbuffer.h"
27 #include "Bluray/bdoverlayscreen.h"
28 #include "tv_actions.h"
29 
30 #define LOC QString("OSD: ")
31 
32 QEvent::Type OSDHideEvent::kEventType =
33  (QEvent::Type) QEvent::registerEventType();
34 
35 ChannelEditor::ChannelEditor(QObject *retobject, const char *name)
36  : MythScreenType((MythScreenType*)nullptr, name)
37 {
38  m_retObject = retobject;
39  m_callsignEdit = nullptr;
40  m_channumEdit = nullptr;
41  m_channameEdit = nullptr;
42  m_xmltvidEdit = nullptr;
43 }
44 
46 {
47  if (!XMLParseBase::LoadWindowFromXML("osd.xml", "ChannelEditor", this))
48  return false;
49 
50  MythUIButton *probeButton = nullptr;
51  MythUIButton *okButton = nullptr;
52 
53  bool err = false;
54  UIUtilE::Assign(this, m_callsignEdit, "callsign", &err);
55  UIUtilE::Assign(this, m_channumEdit, "channum", &err);
56  UIUtilE::Assign(this, m_channameEdit, "channame", &err);
57  UIUtilE::Assign(this, m_xmltvidEdit, "XMLTV", &err);
58  UIUtilE::Assign(this, probeButton, "probe", &err);
59  UIUtilE::Assign(this, okButton, "ok", &err);
60 
61  if (err)
62  {
63  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'ChannelEditor'");
64  return false;
65  }
66 
68  connect(okButton, SIGNAL(Clicked()), SLOT(Confirm()));
69  connect(probeButton, SIGNAL(Clicked()), SLOT(Probe()));
70  SetFocusWidget(okButton);
71 
72  return true;
73 }
74 
76 {
77  sendResult(1);
78 }
79 
81 {
82  sendResult(2);
83 }
84 
86 {
87  if (map.contains("callsign"))
88  m_callsignEdit->SetText(map.value("callsign"));
89  if (map.contains("channum"))
90  m_channumEdit->SetText(map.value("channum"));
91  if (map.contains("channame"))
92  m_channameEdit->SetText(map.value("channame"));
93  if (map.contains("XMLTV"))
94  m_xmltvidEdit->SetText(map.value("XMLTV"));
95 }
96 
98 {
99  map["callsign"] = m_callsignEdit->GetText();
100  map["channum"] = m_channumEdit->GetText();
101  map["channame"] = m_channameEdit->GetText();
102  map["XMLTV"] = m_xmltvidEdit->GetText();
103 }
104 
105 bool ChannelEditor::keyPressEvent(QKeyEvent *event)
106 {
107  if (GetFocusWidget()->keyPressEvent(event))
108  return true;
109 
110  QStringList actions;
111  bool handled = GetMythMainWindow()->TranslateKeyPress("qt", event, actions);
112 
113  for (int i = 0; i < actions.size() && !handled; i++)
114  {
115  QString action = actions[i];
116  if (action == "ESCAPE" )
117  {
118  sendResult(3);
119  handled = true;
120  }
121  }
122 
123  if (!handled && MythScreenType::keyPressEvent(event))
124  handled = true;
125 
126  return handled;
127 }
128 
130 {
131  if (!m_retObject)
132  return;
133 
134  QString message = "";
135  switch (result)
136  {
137  case 1:
138  message = "DIALOG_EDITOR_OK_0";
139  break;
140  case 2:
141  message = "DIALOG_EDITOR_PROBE_0";
142  break;
143  case 3:
144  message = "DIALOG_EDITOR_QUIT_0";
145  break;
146  }
147 
148  DialogCompletionEvent *dce = new DialogCompletionEvent("", result,
149  "", message);
150  QCoreApplication::postEvent(m_retObject, dce);
151 }
152 
153 OSD::OSD(MythPlayer *player, QObject *parent, MythPainter *painter)
154  : m_parent(player), m_ParentObject(parent), m_CurrentPainter(painter),
155  m_Rect(QRect()), m_Effects(true), m_FadeTime(kOSDFadeTime), m_Dialog(nullptr),
156  m_PulsedDialogText(QString()), m_NextPulseUpdate(QDateTime()),
157  m_Refresh(false), m_Visible(false), m_UIScaleOverride(false),
158  m_SavedWMult(1.0f), m_SavedHMult(1.0f), m_SavedUIRect(QRect()),
159  m_fontStretch(100), m_savedFontStretch(100),
160  m_FunctionalType(kOSDFunctionalType_Default), m_FunctionalWindow(QString())
161 {
162  SetTimeouts(3000, 5000, 13000);
163 }
164 
166 {
167  TearDown();
168 }
169 
170 void OSD::TearDown(void)
171 {
172  foreach(MythScreenType* screen, m_Children)
173  delete screen;
174  m_Children.clear();
175  m_Dialog = nullptr;
176 }
177 
178 bool OSD::Init(const QRect &rect, float font_aspect)
179 {
180  m_Rect = rect;
181  m_fontStretch = lroundf(font_aspect * 100);
182  OverrideUIScale();
183  LoadWindows();
184  RevertUIScale();
185 
186  if (m_Children.isEmpty())
187  {
188  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to load any windows.");
189  return false;
190  }
191 
192  LOG(VB_PLAYBACK, LOG_INFO, LOC +
193  QString("Loaded OSD: size %1x%2 offset %3+%4")
194  .arg(m_Rect.width()).arg(m_Rect.height())
195  .arg(m_Rect.left()).arg(m_Rect.top()));
196  HideAll(false);
197  return true;
198 }
199 
201 {
202  if (painter == m_CurrentPainter)
203  return;
204 
205  m_CurrentPainter = painter;
206  QMapIterator<QString, MythScreenType*> it(m_Children);
207  while (it.hasNext())
208  {
209  it.next();
210  it.value()->SetPainter(m_CurrentPainter);
211  }
212 }
213 
215 {
216  QRect uirect = GetMythMainWindow()->GetUIScreenRect();
217  if (uirect == m_Rect)
218  return;
219 
222 
223  int width, height;
225  height, m_SavedHMult);
226  QSize theme_size = MythUIHelper::getMythUI()->GetBaseSize();
227  m_SavedUIRect = uirect;
228  float tmp_wmult = (float)m_Rect.size().width() / (float)theme_size.width();
229  float tmp_hmult = (float)m_Rect.size().height() /
230  (float)theme_size.height();
231  if (log)
232  {
233  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Base theme size: %1x%2")
234  .arg(theme_size.width()).arg(theme_size.height()));
235  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Scaling factors: %1x%2")
236  .arg(tmp_wmult).arg(tmp_hmult));
237  }
238  m_UIScaleOverride = true;
239  GetMythMainWindow()->SetScalingFactors(tmp_wmult, tmp_hmult);
241 }
242 
244 {
245  if (m_UIScaleOverride)
246  {
250  }
251  m_UIScaleOverride = false;
252 }
253 
254 bool OSD::Reinit(const QRect &rect, float font_aspect)
255 {
256  m_Refresh = true;
257  int new_stretch = lroundf(font_aspect * 100);
258  if ((rect == m_Rect) && (new_stretch == m_fontStretch))
259  return true;
260  if (m_Dialog && m_Dialog->objectName() == OSD_DLG_NAVIGATE
261  && m_Dialog->IsVisible())
262  {
263  bool softBlend = (m_parent->GetVideoOutput()->GetOSDRenderer() == "softblend");
264  OsdNavigation *nav = static_cast<OsdNavigation *> (m_Dialog);
265  QString navFocus = nav->GetFocusWidget()->objectName();
266  if (softBlend && navFocus == "TOGGLEFILL")
267  // in this case continue with reinit
268  ;
269  else
270  return true;
271  }
272 
273  HideAll(false);
274  TearDown();
275  if (!Init(rect, font_aspect))
276  {
277  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to re-init OSD."));
278  return false;
279  }
280  return true;
281 }
282 
283 bool OSD::IsVisible(void)
284 {
285  if (GetNotificationCenter()->DisplayedNotifications() > 0)
286  return true;
287 
288  foreach(MythScreenType* child, m_Children)
289  {
290  if (child->IsVisible() &&
291  child->objectName() != OSD_WIN_SUBTITLE &&
292  child->objectName() != OSD_WIN_TELETEXT &&
293  child->objectName() != OSD_WIN_BDOVERLAY &&
294  child->objectName() != OSD_WIN_INTERACT)
295  return true;
296  }
297 
298  return false;
299 }
300 
301 void OSD::HideAll(bool keepsubs, MythScreenType* except, bool dropnotification)
302 {
303  if (dropnotification)
304  {
305  if (GetNotificationCenter()->RemoveFirst())
306  return; // we've removed the top window, don't process any further
307  }
308  QMutableMapIterator<QString, MythScreenType*> it(m_Children);
309  while (it.hasNext())
310  {
311  it.next();
312  if (except && except->objectName() == OSD_DLG_NAVIGATE
313  && it.value()->objectName() == "osd_status")
314  continue;
315  bool match1 = keepsubs &&
316  (it.key() == OSD_WIN_SUBTITLE ||
317  it.key() == OSD_WIN_TELETEXT);
318  bool match2 = it.key() == OSD_WIN_BDOVERLAY ||
319  it.key() == OSD_WIN_INTERACT ||
320  it.value() == except;
321  if (!(match1 || match2))
322  HideWindow(it.key());
323  }
324 }
325 
327 {
328  static const char* default_windows[7] = {
329  "osd_message", "osd_input", "program_info", "browse_info", "osd_status",
330  "osd_program_editor", "osd_debug"};
331 
332  for (int i = 0; i < 7; i++)
333  {
334  const char* window = default_windows[i];
335  MythOSDWindow *win = new MythOSDWindow(nullptr, window, true);
336 
338  if (win->Create())
339  {
340  PositionWindow(win);
341  LOG(VB_PLAYBACK, LOG_INFO, LOC +
342  QString("Loaded window %1").arg(window));
343  m_Children.insert(window, win);
344  }
345  else
346  {
347  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to load window %1")
348  .arg(window));
349  delete win;
350  }
351  }
352 }
353 
354 void OSD::SetValues(const QString &window, const QHash<QString,int> &map,
356 {
357  MythScreenType *win = GetWindow(window);
358  if (!win)
359  return;
360 
361  bool found = false;
362  if (map.contains("position"))
363  {
364  MythUIProgressBar *bar = dynamic_cast<MythUIProgressBar *> (win->GetChild("position"));
365  if (bar)
366  {
367  bar->SetVisible(true);
368  bar->SetStart(0);
369  bar->SetTotal(1000);
370  bar->SetUsed(map.value("position"));
371  found = true;
372  }
373  }
374  if (map.contains("relposition"))
375  {
376  MythUIProgressBar *bar = dynamic_cast<MythUIProgressBar *> (win->GetChild("relposition"));
377  if (bar)
378  {
379  bar->SetVisible(true);
380  bar->SetStart(0);
381  bar->SetTotal(1000);
382  bar->SetUsed(map.value("relposition"));
383  found = true;
384  }
385  }
386 
387  if (found)
388  SetExpiry(window, timeout);
389 }
390 
391 void OSD::SetValues(const QString &window, const QHash<QString,float> &map,
393 {
394  MythScreenType *win = GetWindow(window);
395  if (!win)
396  return;
397 
398  bool found = false;
399  if (map.contains("position"))
400  {
401  MythUIEditBar *edit = dynamic_cast<MythUIEditBar *> (win->GetChild("editbar"));
402  if (edit)
403  {
404  edit->SetEditPosition(map.value("position"));
405  found = true;
406  }
407  }
408 
409  if (found)
410  SetExpiry(window, timeout);
411 }
412 
413 void OSD::SetText(const QString &window, const InfoMap &map,
415 {
416  MythScreenType *win = GetWindow(window);
417  if (!win)
418  return;
419 
420  if (map.contains("numstars"))
421  {
422  MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("ratingstate"));
423  if (state)
424  state->DisplayState(map["numstars"]);
425  }
426  if (map.contains("tvstate"))
427  {
428  MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("tvstate"));
429  if (state)
430  state->DisplayState(map["tvstate"]);
431  }
432  if (map.contains("videocodec"))
433  {
434  MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("videocodec"));
435  if (state)
436  state->DisplayState(map["videocodec"]);
437  }
438  if (map.contains("videodescrip"))
439  {
440  MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("videodescrip"));
441  if (state)
442  state->DisplayState(map["videodescrip"]);
443  }
444  if (map.contains("audiocodec"))
445  {
446  MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("audiocodec"));
447  if (state)
448  state->DisplayState(map["audiocodec"]);
449  }
450  if (map.contains("audiochannels"))
451  {
452  MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("audiochannels"));
453  if (state)
454  state->DisplayState(map["audiochannels"]);
455  }
456  if (map.contains("chanid"))
457  {
458  MythUIImage *icon = dynamic_cast<MythUIImage *> (win->GetChild("iconpath"));
459  if (icon)
460  {
461  icon->Reset();
462 
463  uint chanid = map["chanid"].toUInt();
464  QString iconpath;
465  if (map.contains("iconpath"))
466  iconpath = map["iconpath"];
467  else
468  iconpath = ChannelUtil::GetIcon(chanid);
469 
470  if (!iconpath.isEmpty())
471  {
472  QString iconurl =
473  gCoreContext->GetMasterHostPrefix("ChannelIcons",
474  iconpath);
475 
476  icon->SetFilename(iconurl);
477  icon->Load(false);
478  }
479  }
480  }
481 
482  if (map.contains("channelgroup"))
483  {
484  MythUIText *textArea = dynamic_cast<MythUIText *> (win->GetChild("channelgroup"));
485  if (textArea)
486  {
487  textArea->SetText(map["channelgroup"]);
488  }
489  }
490 
491  if (map.contains("inetref"))
492  {
493  MythUIImage *cover = dynamic_cast<MythUIImage *> (win->GetChild("coverart"));
494  if (cover && map.contains("coverartpath"))
495  {
496  QString coverpath = map["coverartpath"];
497  cover->SetFilename(coverpath);
498  cover->Load(false);
499  }
500  MythUIImage *fanart = dynamic_cast<MythUIImage *> (win->GetChild("fanart"));
501  if (fanart && map.contains("fanartpath"))
502  {
503  QString fanartpath = map["fanartpath"];
504  fanart->SetFilename(fanartpath);
505  fanart->Load(false);
506  }
507  MythUIImage *banner = dynamic_cast<MythUIImage *> (win->GetChild("banner"));
508  if (banner && map.contains("bannerpath"))
509  {
510  QString bannerpath = map["bannerpath"];
511  banner->SetFilename(bannerpath);
512  banner->Load(false);
513  }
514  MythUIImage *screenshot = dynamic_cast<MythUIImage *> (win->GetChild("screenshot"));
515  if (screenshot && map.contains("screenshotpath"))
516  {
517  QString screenshotpath = map["screenshotpath"];
518  screenshot->SetFilename(screenshotpath);
519  screenshot->Load(false);
520  }
521  }
522  if (map.contains("nightmode"))
523  {
524  MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("nightmode"));
525  if (state)
526  state->DisplayState(map["nightmode"]);
527  }
528  if (map.contains("mediatype"))
529  {
530  MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("mediatype"));
531  if (state)
532  state->DisplayState(map["mediatype"]);
533  }
534 
535  MythUIProgressBar *bar =
536  dynamic_cast<MythUIProgressBar *>(win->GetChild("elapsedpercent"));
537  if (bar)
538  {
539 #if QT_VERSION < QT_VERSION_CHECK(5,8,0)
540  int startts = map["startts"].toInt();
541  int endts = map["endts"].toInt();
542  int nowts = MythDate::current().toTime_t();
543 #else
544  qint64 startts = map["startts"].toLongLong();
545  qint64 endts = map["endts"].toLongLong();
546  qint64 nowts = MythDate::current().toSecsSinceEpoch();
547 #endif
548  if (startts > nowts)
549  {
550  bar->SetUsed(0);
551  }
552  else if (endts < nowts)
553  {
554  bar->SetUsed(1000);
555  }
556  else
557  {
558 #if QT_VERSION < QT_VERSION_CHECK(5,8,0)
559  int duration = endts - startts;
560 #else
561  qint64 duration = endts - startts;
562 #endif
563  if (duration > 0)
564  bar->SetUsed(1000 * (nowts - startts) / duration);
565  else
566  bar->SetUsed(0);
567  }
568  bar->SetVisible(startts > 0);
569  bar->SetStart(0);
570  bar->SetTotal(1000);
571  }
572 
573  win->SetVisible(true);
574 
575  if (win == m_Dialog)
576  {
577  ChannelEditor *edit = dynamic_cast<ChannelEditor*>(m_Dialog);
578  if (edit)
579  edit->SetText(map);
580  else
581  win->SetTextFromMap(map);
582  }
583  else
584  win->SetTextFromMap(map);
585 
586  SetExpiry(window, timeout);
587 }
588 
589 void OSD::SetRegions(const QString &window, frm_dir_map_t &map,
590  long long total)
591 {
592  MythScreenType *win = GetWindow(window);
593  if (!win)
594  return;
595 
596  MythUIEditBar *bar = dynamic_cast<MythUIEditBar*>(win->GetChild("editbar"));
597  if (!bar)
598  return;
599 
600  bar->ClearRegions();
601  if (!map.size() || total < 1)
602  {
603  bar->Display();
604  return;
605  }
606 
607  long long start = -1;
608  long long end = -1;
609  bool first = true;
610  QMapIterator<uint64_t, MarkTypes> it(map);
611  while (it.hasNext())
612  {
613  bool error = false;
614  it.next();
615  if (it.value() == MARK_CUT_START)
616  {
617  start = it.key();
618  if (end > -1)
619  error = true;
620  }
621  else if (it.value() == MARK_CUT_END)
622  {
623  if (first)
624  start = 0;
625  if (start < 0)
626  error = true;
627  end = it.key();
628  }
629  else if (it.value() == MARK_PLACEHOLDER)
630  {
631  start = end = it.key();
632  }
633  first = false;
634 
635  if (error)
636  {
637  LOG(VB_GENERAL, LOG_ERR, LOC + "deleteMap discontinuity");
638  start = -1;
639  end = -1;
640  }
641 
642  if (start >=0 && end >= 0)
643  {
644  bar->AddRegion((float)((double)start/(double)total),
645  (float)((double)end/(double)total));
646  start = -1;
647  end = -1;
648  }
649  }
650  if (start > -1 && end < 0)
651  bar->AddRegion((float)((double)start/(double)total), 1.0f);
652 
653  bar->Display();
654 }
655 
656 void OSD::SetGraph(const QString &window, const QString &graph, int64_t timecode)
657 {
658  MythScreenType *win = GetWindow(window);
659  if (!win)
660  return;
661 
662  MythUIImage *image = dynamic_cast<MythUIImage* >(win->GetChild(graph));
663  if (!image)
664  return;
665 
666  MythImage* mi = m_parent->GetAudioGraph().GetImage(timecode);
667  if (mi)
668  image->SetImage(mi);
669 }
670 
671 bool OSD::DrawDirect(MythPainter* painter, QSize size, bool repaint)
672 {
673  if (!painter)
674  return false;
675 
676  bool visible = false;
677  bool redraw = m_Refresh;
678  m_Refresh = false;
679  QTime now = MythDate::current().time();
680 
681  CheckExpiry();
682  QMap<QString,MythScreenType*>::const_iterator it;
683  for (it = m_Children.begin(); it != m_Children.end(); ++it)
684  {
685  if ((*it)->IsVisible())
686  {
687  visible = true;
688  (*it)->Pulse();
689  if (m_Effects && m_ExpireTimes.contains((*it)))
690  {
691  QTime expires = m_ExpireTimes.value((*it)).time();
692  int left = now.msecsTo(expires);
693  if (left < m_FadeTime)
694  (*it)->SetAlpha((255 * left) / m_FadeTime);
695  }
696  if ((*it)->NeedsRedraw())
697  redraw = true;
698  }
699  }
700 
702  QList<MythScreenType*> notifications;
703  nc->GetNotificationScreens(notifications);
704  QList<MythScreenType*>::iterator it2 = notifications.begin();
705  while (it2 != notifications.end())
706  {
707  if (!nc->ScreenCreated(*it2))
708  {
709  LOG(VB_GUI, LOG_DEBUG, LOC + "Creating OSD Notification");
710 
711  if (!m_UIScaleOverride)
712  {
713  OverrideUIScale(false);
714  }
715  (*it2)->SetPainter(m_CurrentPainter);
716  if (!(*it2)->Create())
717  {
718  it2 = notifications.erase(it2);
719  continue;
720  }
721  }
722  if ((*it2)->IsVisible())
723  {
724  if (!m_UIScaleOverride)
725  {
726  OverrideUIScale(false);
727  }
728 
729  (*it2)->SetPainter(m_CurrentPainter);
730 
731  nc->UpdateScreen(*it2);
732 
733  visible = true;
734  (*it2)->Pulse();
735  if (m_Effects)
736  {
737  QTime expires = nc->ScreenExpiryTime(*it2).time();
738  int left = now.msecsTo(expires);
739  if (left < 0)
740  left = 0;
741  if (expires.isValid() && left < m_FadeTime)
742  (*it2)->SetAlpha((255 * left) / m_FadeTime);
743  }
744  if ((*it2)->NeedsRedraw())
745  redraw = true;
746  }
747  ++it2;
748  }
749  RevertUIScale();
750 
751  redraw |= repaint;
752 
753  if (redraw && visible)
754  {
755  QRect cliprect = QRect(QPoint(0, 0), size);
756  painter->Begin(nullptr);
757  for (it = m_Children.begin(); it != m_Children.end(); ++it)
758  {
759  if ((*it)->IsVisible())
760  {
761  (*it)->Draw(painter, 0, 0, 255, cliprect);
762  (*it)->SetAlpha(255);
763  (*it)->ResetNeedsRedraw();
764  }
765  }
766  for (it2 = notifications.begin(); it2 != notifications.end(); ++it2)
767  {
768  if ((*it2)->IsVisible())
769  {
770  (*it2)->Draw(painter, 0, 0, 255, cliprect);
771  (*it2)->SetAlpha(255);
772  (*it2)->ResetNeedsRedraw();
773  }
774  }
775  painter->End();
776  }
777 
778  // Force a redraw if it just became invisible
779  if (m_Visible && !visible)
780  redraw=true;
781  m_Visible = visible;
782 
783  return redraw;
784 }
785 
786 QRegion OSD::Draw(MythPainter* painter, QPaintDevice *device, QSize size,
787  QRegion &changed, int alignx, int aligny)
788 {
789  bool redraw = m_Refresh;
790  QRegion visible = QRegion();
791  QRegion dirty = m_Refresh ? QRegion(QRect(QPoint(0,0), m_Rect.size())) :
792  QRegion();
793  m_Refresh = false;
794 
795  if (!painter || !device)
796  return visible;
797 
798  QTime now = MythDate::current().time();
799  CheckExpiry();
800 
801  // first update for alpha pulse and fade
802  QMap<QString,MythScreenType*>::const_iterator it;
803  for (it = m_Children.begin(); it != m_Children.end(); ++it)
804  {
805  if ((*it)->IsVisible())
806  {
807  QRect vis = (*it)->GetArea().toQRect();
808  if (visible.isEmpty())
809  visible = QRegion(vis);
810  else
811  visible = visible.united(vis);
812 
813  (*it)->Pulse();
814  if (m_Effects && m_ExpireTimes.contains((*it)))
815  {
816  QTime expires = m_ExpireTimes.value((*it)).time();
817  int left = now.msecsTo(expires);
818  if (left < m_FadeTime)
819  (*it)->SetAlpha((255 * left) / m_FadeTime);
820  }
821  }
822 
823  if ((*it)->NeedsRedraw())
824  {
825  QRegion area = (*it)->GetDirtyArea();
826  dirty = dirty.united(area);
827  redraw = true;
828  }
829  }
830 
832  QList<MythScreenType*> notifications;
833  nc->GetNotificationScreens(notifications);
834  QList<MythScreenType*>::iterator it2 = notifications.begin();
835  while (it2 != notifications.end())
836  {
837  if (!GetNotificationCenter()->ScreenCreated(*it2))
838  {
839  if (!m_UIScaleOverride)
840  {
841  OverrideUIScale(false);
842  }
843  (*it2)->SetPainter(m_CurrentPainter);
844  if (!(*it2)->Create())
845  {
846  it2 = notifications.erase(it2);
847  continue;
848  }
849  }
850  if ((*it2)->IsVisible())
851  {
852  if (!m_UIScaleOverride)
853  {
854  OverrideUIScale(false);
855  }
856  nc->UpdateScreen(*it2);
857 
858  QRect vis = (*it2)->GetArea().toQRect();
859  if (visible.isEmpty())
860  visible = QRegion(vis);
861  else
862  visible = visible.united(vis);
863 
864  (*it2)->Pulse();
865  if (m_Effects)
866  {
867  QTime expires = nc->ScreenExpiryTime(*it2).time();
868  int left = now.msecsTo(expires);
869  if (expires.isValid() && left < m_FadeTime)
870  (*it2)->SetAlpha((255 * left) / m_FadeTime);
871  }
872  }
873 
874  if ((*it2)->NeedsRedraw())
875  {
876  QRegion area = (*it2)->GetDirtyArea();
877  dirty = dirty.united(area);
878  redraw = true;
879  }
880  ++it2;
881  }
882  RevertUIScale();
883 
884  if (redraw)
885  {
886  // clear the dirty area
887  painter->Clear(device, dirty);
888 
889  // set redraw for any widgets that may now need a partial repaint
890  for (it = m_Children.begin(); it != m_Children.end(); ++it)
891  {
892  if ((*it)->IsVisible() && !(*it)->NeedsRedraw() &&
893  dirty.intersects((*it)->GetArea().toQRect()))
894  {
895  (*it)->SetRedraw();
896  }
897  }
898 
899  for (it2 = notifications.begin(); it2 != notifications.end(); ++it2)
900  {
901  if ((*it2)->IsVisible() && !(*it2)->NeedsRedraw() &&
902  dirty.intersects((*it2)->GetArea().toQRect()))
903  {
904  (*it2)->SetRedraw();
905  }
906  }
907 
908  // and finally draw
909  QRect cliprect = dirty.boundingRect();
910  painter->Begin(device);
911  painter->SetClipRegion(dirty);
912  // TODO painting in reverse may be more efficient...
913  for (it = m_Children.begin(); it != m_Children.end(); ++it)
914  {
915  if ((*it)->NeedsRedraw())
916  {
917  if ((*it)->IsVisible())
918  (*it)->Draw(painter, 0, 0, 255, cliprect);
919  (*it)->SetAlpha(255);
920  (*it)->ResetNeedsRedraw();
921  }
922  }
923 
924  for (it2 = notifications.begin(); it2 != notifications.end(); ++it2)
925  {
926  if ((*it2)->NeedsRedraw())
927  {
928  if ((*it2)->IsVisible())
929  (*it2)->Draw(painter, 0, 0, 255, cliprect);
930  (*it2)->SetAlpha(255);
931  (*it2)->ResetNeedsRedraw();
932  }
933  }
934 
935  painter->End();
936  }
937 
938  changed = dirty;
939 
940  if (visible.isEmpty() || (!alignx && !aligny))
941  return visible;
942 
943  // assist yuv blending with some friendly alignments
944  QRegion aligned;
945  QVector<QRect> rects = visible.rects();
946  for (int i = 0; i < rects.size(); i++)
947  {
948  QRect r = rects[i];
949  int left = r.left() & ~(alignx - 1);
950  int top = r.top() & ~(aligny - 1);
951  int right = (r.left() + r.width());
952  int bot = (r.top() + r.height());
953  if (right & (alignx - 1))
954  right += alignx - (right & (alignx - 1));
955  if (bot % aligny)
956  bot += aligny - (bot % aligny);
957  aligned = aligned.united(QRegion(left, top, right - left, bot - top));
958  }
959 
960  return aligned.intersected(QRect(QPoint(0,0), size));
961 }
962 
964 {
965  QDateTime now = MythDate::current();
966  QMutableHashIterator<MythScreenType*, QDateTime> it(m_ExpireTimes);
967  while (it.hasNext())
968  {
969  it.next();
970  if (it.value() < now)
971  {
972  if (it.key() == m_Dialog)
973  DialogQuit();
974  else
975  HideWindow(m_Children.key(it.key()));
976  }
977  else if (it.key() == m_Dialog)
978  {
979  if (!m_PulsedDialogText.isEmpty() && now > m_NextPulseUpdate)
980  {
981  QString newtext = m_PulsedDialogText;
982  MythDialogBox *dialog = dynamic_cast<MythDialogBox*>(m_Dialog);
983  if (dialog)
984  {
985  // The disambiguation string must be an empty string
986  // and not a NULL to get extracted by the Qt tools.
987  QString replace = QCoreApplication::translate("(Common)",
988  "%n second(s)",
989  "",
990  now.secsTo(it.value()));
991  dialog->SetText(newtext.replace("%d", replace));
992  }
993  MythConfirmationDialog *cdialog = dynamic_cast<MythConfirmationDialog*>(m_Dialog);
994  if (cdialog)
995  {
996  QString replace = QString::number(now.secsTo(it.value()));
997  cdialog->SetMessage(newtext.replace("%d", replace));
998  }
999  m_NextPulseUpdate = now.addSecs(1);
1000  }
1001  }
1002  }
1003 }
1004 
1005 void OSD::SetExpiry(const QString &window, enum OSDTimeout timeout,
1006  int custom_timeout)
1007 {
1008  SetExpiry1(window, timeout, custom_timeout);
1009  if (IsWindowVisible(window))
1010  {
1011  // Keep status and nav timeouts in sync
1012  if (window == OSD_DLG_NAVIGATE)
1013  SetExpiry1("osd_status", timeout, custom_timeout);
1014  else if (window == "osd_status" && IsWindowVisible(OSD_DLG_NAVIGATE))
1015  SetExpiry1(OSD_DLG_NAVIGATE, timeout, custom_timeout);
1016  }
1017 }
1018 
1019 void OSD::SetExpiry1(const QString &window, enum OSDTimeout timeout,
1020  int custom_timeout)
1021 {
1022  if (timeout == kOSDTimeout_Ignore && !custom_timeout)
1023  return;
1024 
1025  MythScreenType *win = GetWindow(window);
1026  int time = custom_timeout ? custom_timeout : m_Timeouts[timeout];
1027  if ((time > 0) && win)
1028  {
1029  QDateTime expires = MythDate::current().addMSecs(time);
1030  m_ExpireTimes.insert(win, expires);
1031  }
1032  else if ((time < 0) && win)
1033  {
1034  if (m_ExpireTimes.contains(win))
1035  m_ExpireTimes.remove(win);
1036  }
1037 }
1038 
1039 void OSD::SetTimeouts(int _short, int _medium, int _long)
1040 {
1042  m_Timeouts[kOSDTimeout_Short] = _short;
1043  m_Timeouts[kOSDTimeout_Med] = _medium;
1044  m_Timeouts[kOSDTimeout_Long] = _long;
1045 }
1046 
1047 bool OSD::IsWindowVisible(const QString &window)
1048 {
1049  if (!m_Children.contains(window))
1050  return false;
1051 
1052  return m_Children.value(window)->IsVisible(/*true*/);
1053 }
1054 
1055 void OSD::ResetWindow(const QString &window)
1056 {
1057  if (!m_Children.contains(window))
1058  return;
1059 
1060  m_Children.value(window)->Reset();
1061 }
1062 
1064 {
1065  if (!window)
1066  return;
1067 
1068  MythRect rect = window->GetArea();
1069  rect.translate(m_Rect.left(), m_Rect.top());
1070  window->SetArea(rect);
1071 }
1072 
1073 void OSD::RemoveWindow(const QString &window)
1074 {
1075  if (!m_Children.contains(window))
1076  return;
1077 
1078  HideWindow(window);
1079  MythScreenType *child = m_Children.value(window);
1080  m_Children.remove(window);
1081  delete child;
1082 }
1083 
1084 MythScreenType *OSD::GetWindow(const QString &window)
1085 {
1086  if (m_Children.contains(window))
1087  return m_Children.value(window);
1088 
1089  MythScreenType *new_window = nullptr;
1090 
1091  if (window == OSD_WIN_INTERACT)
1092  {
1093  new_window = new InteractiveScreen(m_parent, window);
1094  }
1095  else if (window == OSD_WIN_BDOVERLAY)
1096  {
1097  new_window = new BDOverlayScreen(m_parent, window);
1098  }
1099  else
1100  {
1101  new_window = new MythOSDWindow(nullptr, window, false);
1102  }
1103 
1104  new_window->SetPainter(m_CurrentPainter);
1105  if (new_window->Create())
1106  {
1107  m_Children.insert(window, new_window);
1108  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1109  QString("Created window %1").arg(window));
1110  return new_window;
1111  }
1112 
1113  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to create window %1")
1114  .arg(window));
1115  delete new_window;
1116  return nullptr;
1117 }
1118 
1119 void OSD::SetFunctionalWindow(const QString &window, enum OSDFunctionalType type)
1120 {
1123  SendHideEvent();
1124 
1125  m_FunctionalWindow = window;
1127 }
1128 
1129 void OSD::HideWindow(const QString &window)
1130 {
1131  if (!m_Children.contains(window))
1132  return;
1133  m_Children.value(window)->SetVisible(false);
1134  m_Children.value(window)->Close(); // for InteractiveScreen
1135  SetExpiry(window, kOSDTimeout_None);
1136  m_Refresh = true;
1137 
1139  {
1140  bool valid = m_Children.contains(m_FunctionalWindow);
1141  bool visible = valid && m_Children.value(m_FunctionalWindow)->IsVisible(false);
1142  if (!valid || !visible)
1143  {
1144  SendHideEvent();
1146  m_FunctionalWindow = QString();
1147  }
1148  }
1149 }
1150 
1152 {
1154  QCoreApplication::postEvent(m_ParentObject, event);
1155 }
1156 
1157 bool OSD::HasWindow(const QString &window)
1158 {
1159  return m_Children.contains(window);
1160 }
1161 
1162 bool OSD::DialogVisible(QString window)
1163 {
1164  if (!m_Dialog || window.isEmpty())
1165  return m_Dialog;
1166 
1167  return m_Dialog->objectName() == window;
1168 }
1169 
1170 bool OSD::DialogHandleKeypress(QKeyEvent *e)
1171 {
1172  if (!m_Dialog)
1173  return false;
1174  return m_Dialog->keyPressEvent(e);
1175 }
1176 
1178 {
1179  if (!m_Dialog)
1180  return false;
1181  return m_Dialog->gestureEvent(e);
1182 }
1183 
1185 {
1186  if (!m_Dialog)
1187  return;
1188 
1189  RemoveWindow(m_Dialog->objectName());
1190  m_Dialog = nullptr;
1191  m_PulsedDialogText = QString();
1192 }
1193 
1194 void OSD::DialogShow(const QString &window, const QString &text, int updatefor)
1195 {
1196  if (m_Dialog)
1197  {
1198  QString current = m_Dialog->objectName();
1199  if (current != window)
1200  {
1201  DialogQuit();
1202  }
1203  else
1204  {
1205  MythDialogBox *dialog = dynamic_cast<MythDialogBox*>(m_Dialog);
1206  if (dialog)
1207  dialog->Reset();
1208 
1209  DialogSetText(text);
1210  }
1211  }
1212 
1213  if (!m_Dialog)
1214  {
1215  OverrideUIScale();
1216  MythScreenType *dialog;
1217 
1218  if (window == OSD_DLG_EDITOR)
1219  dialog = new ChannelEditor(m_ParentObject, window.toLatin1());
1220  else if (window == OSD_DLG_CONFIRM)
1221  dialog = new MythConfirmationDialog(nullptr, text, false);
1222  else if (window == OSD_DLG_NAVIGATE)
1223  dialog = new OsdNavigation(m_ParentObject, window, this);
1224  else
1225  dialog = new MythDialogBox(text, nullptr, window.toLatin1(), false, true);
1226 
1227  dialog->SetPainter(m_CurrentPainter);
1228  if (dialog->Create())
1229  {
1230  PositionWindow(dialog);
1231  m_Dialog = dialog;
1232  MythDialogBox *dbox = dynamic_cast<MythDialogBox*>(m_Dialog);
1233  if (dbox)
1234  dbox->SetReturnEvent(m_ParentObject, window);
1235  MythConfirmationDialog *cbox = dynamic_cast<MythConfirmationDialog*>(m_Dialog);
1236  if (cbox)
1237  {
1238  cbox->SetReturnEvent(m_ParentObject, window);
1239  cbox->SetData("DIALOG_CONFIRM_X_X");
1240  }
1241  m_Children.insert(window, m_Dialog);
1242  }
1243  else
1244  {
1245  RevertUIScale();
1246  delete dialog;
1247  return;
1248  }
1249 
1250  RevertUIScale();
1251  }
1252 
1253  if (updatefor)
1254  {
1256  m_PulsedDialogText = text;
1257  SetExpiry(window, kOSDTimeout_None, updatefor);
1258  }
1259 
1260  DialogBack();
1261  HideAll(true, m_Dialog);
1262  m_Dialog->SetVisible(true);
1263 }
1264 
1265 void OSD::DialogSetText(const QString &text)
1266 {
1267  MythDialogBox *dialog = dynamic_cast<MythDialogBox*>(m_Dialog);
1268  if (dialog)
1269  dialog->SetText(text);
1270 }
1271 
1272 void OSD::DialogBack(QString text, QVariant data, bool exit)
1273 {
1274  MythDialogBox *dialog = dynamic_cast<MythDialogBox*>(m_Dialog);
1275  if (dialog)
1276  {
1277  dialog->SetBackAction(text, data);
1278  if (exit)
1279  dialog->SetExitAction(text, data);
1280  }
1281 }
1282 
1283 void OSD::DialogAddButton(QString text, QVariant data, bool menu, bool current)
1284 {
1285  MythDialogBox *dialog = dynamic_cast<MythDialogBox*>(m_Dialog);
1286  if (dialog)
1287  dialog->AddButton(text, data, menu, current);
1288 }
1289 
1291 {
1292  ChannelEditor *edit = dynamic_cast<ChannelEditor*>(m_Dialog);
1293  if (edit)
1294  edit->GetText(map);
1295 }
1296 
1298 {
1299  TeletextScreen *tt = nullptr;
1300  if (m_Children.contains(OSD_WIN_TELETEXT))
1301  {
1303  }
1304  else
1305  {
1306  OverrideUIScale();
1308 
1310  if (tt->Create())
1311  {
1312  m_Children.insert(OSD_WIN_TELETEXT, tt);
1313  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created window %1")
1314  .arg(OSD_WIN_TELETEXT));
1315  }
1316  else
1317  {
1318  delete tt;
1319  tt = nullptr;
1320  }
1321  RevertUIScale();
1322  }
1323  if (!tt)
1324  {
1325  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Teletext window");
1326  return nullptr;
1327  }
1328 
1330  tt->SetDisplaying(false);
1331  return tt;
1332 }
1333 
1334 void OSD::EnableTeletext(bool enable, int page)
1335 {
1336  TeletextScreen *tt = InitTeletext();
1337  if (!tt)
1338  return;
1339 
1340  tt->SetVisible(enable);
1341  tt->SetDisplaying(enable);
1342  if (enable)
1343  {
1344  tt->SetPage(page, -1);
1345  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Enabled teletext page %1")
1346  .arg(page));
1347  }
1348  else
1349  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Disabled teletext");
1350 }
1351 
1352 bool OSD::TeletextAction(const QString &action)
1353 {
1355  return false;
1356 
1358  if (tt)
1359  return tt->KeyPress(action);
1360  return false;
1361 }
1362 
1364 {
1366  return;
1367 
1368  TeletextScreen* tt = InitTeletext();
1369  if (tt)
1370  tt->Reset();
1371 }
1372 
1374 {
1376  return;
1377 
1379  if (tt)
1380  tt->ClearScreen();
1381 }
1382 
1384 {
1385  SubtitleScreen *sub = nullptr;
1386  if (m_Children.contains(OSD_WIN_SUBTITLE))
1387  {
1389  }
1390  else
1391  {
1392  OverrideUIScale();
1395  if (sub->Create())
1396  {
1397  m_Children.insert(OSD_WIN_SUBTITLE, sub);
1398  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created window %1")
1399  .arg(OSD_WIN_SUBTITLE));
1400  }
1401  else
1402  {
1403  delete sub;
1404  sub = nullptr;
1405  }
1406  RevertUIScale();
1407  }
1408  if (!sub)
1409  {
1410  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create subtitle window");
1411  return nullptr;
1412  }
1413  return sub;
1414 }
1415 
1416 void OSD::EnableSubtitles(int type, bool forced_only)
1417 {
1418  SubtitleScreen *sub = InitSubtitles();
1419  if (sub)
1420  sub->EnableSubtitles(type, forced_only);
1421 }
1422 
1424 {
1426  return;
1427 
1428  SubtitleScreen *sub = InitSubtitles();
1429  sub->DisableForcedSubtitles();
1430 }
1431 
1433 {
1435  return;
1436 
1437  SubtitleScreen* sub = InitSubtitles();
1438  if (sub)
1439  sub->ClearAllSubtitles();
1440 }
1441 
1442 void OSD::DisplayDVDButton(AVSubtitle* dvdButton, QRect &pos)
1443 {
1444  if (!dvdButton)
1445  return;
1446 
1447  SubtitleScreen* sub = InitSubtitles();
1448  if (sub)
1449  {
1451  sub->DisplayDVDButton(dvdButton, pos);
1452  }
1453 }
1454 
1456 {
1457  if (!overlay)
1458  return;
1459 
1461  if (bd)
1462  bd->DisplayBDOverlay(overlay);
1463 }
1464 
1465 OsdNavigation::OsdNavigation(QObject *retobject, const QString &name, OSD *osd)
1466  : MythScreenType((MythScreenType*)nullptr, name),
1467  m_retObject(retobject),
1468  m_osd(osd),
1469  m_playButton(nullptr),
1470  m_pauseButton(nullptr),
1471  m_muteButton(nullptr),
1472  m_unMuteButton(nullptr),
1473  m_paused('X'),
1474  m_muted('X'),
1475  m_visibleGroup(0),
1476  m_maxGroupNum(-1),
1477  m_IsVolumeControl(true)
1478 {
1479  m_retObject = retobject;
1480 }
1481 
1483 {
1484  if (!XMLParseBase::LoadWindowFromXML("osd.xml", "osd_navigation", this))
1485  return false;
1486 
1487  MythUIButton *moreButton;
1488  UIUtilW::Assign(this, moreButton, "more");
1489  if (moreButton)
1490  connect(moreButton, SIGNAL(Clicked()), SLOT(More()));
1491  UIUtilW::Assign(this, m_pauseButton, "PAUSE");
1492  UIUtilW::Assign(this, m_playButton, "PLAY");
1493  UIUtilW::Assign(this, m_muteButton, "MUTE");
1494  UIUtilW::Assign(this, m_unMuteButton, "unmute");
1495 
1496  MythPlayer *player = m_osd->GetPlayer();
1497 
1498  if (!player || !player->HasAudioOut() ||
1499  !player->PlayerControlsVolume())
1500  {
1501  m_IsVolumeControl = false;
1502  if (m_muteButton)
1503  m_muteButton->Hide();
1504  if (m_unMuteButton)
1505  m_unMuteButton->Hide();
1506  }
1507 
1508  // find number of groups and make sure only corrrect one is visible
1509  MythUIGroup *group;
1510  for (int i = 0; i < 100 ; i++)
1511  {
1512  UIUtilW::Assign(this, group, QString("grp%1").arg(i));
1513  if (group)
1514  {
1515  m_maxGroupNum = i;
1516  if (i != m_visibleGroup)
1517  group->SetVisible (false);
1518  QList<MythUIType *> * children = group->GetAllChildren();
1519  QList<MythUIType *>::iterator it;
1520  for (it = children->begin(); it != children->end(); ++it)
1521  {
1522  MythUIType *child = *it;
1523  if (child == moreButton)
1524  continue;
1525  connect(child, SIGNAL(Clicked()), SLOT(GeneralAction()));
1526  }
1527  }
1528  else
1529  break;
1530  }
1531 
1532  BuildFocusList();
1533 
1534  return true;
1535 }
1536 
1537 bool OsdNavigation::keyPressEvent(QKeyEvent *event)
1538 {
1539  // bool extendTimeout = (m_paused != 'Y');
1540  bool extendTimeout = true;
1541  bool handled = false;
1542 
1543  MythUIType *focus = GetFocusWidget();
1544  if (focus && focus->keyPressEvent(event))
1545  handled = true;
1546 
1547  if (!handled)
1548  {
1549  QStringList actions;
1550  handled = GetMythMainWindow()->TranslateKeyPress("qt", event, actions);
1551 
1552  for (int i = 0; i < actions.size() && !handled; i++)
1553  {
1554  QString action = actions[i];
1555  if (action == "ESCAPE" )
1556  {
1557  sendResult(-1,action);
1558  handled = true;
1559  extendTimeout = false;
1560  }
1561  }
1562  }
1563  if (!handled && MythScreenType::keyPressEvent(event))
1564  handled = true;
1565 
1566  if (extendTimeout)
1567  {
1569  // m_osd->SetExpiry("osd_status", kOSDTimeout_Long);
1570  }
1571 
1572  return handled;
1573 }
1574 
1575 // Virtual
1577 {
1578  sendResult(100,"MENU");
1579 }
1580 
1581 void OsdNavigation::sendResult(int result, QString action)
1582 {
1583  if (!m_retObject)
1584  return;
1585 
1586  DialogCompletionEvent *dce = new DialogCompletionEvent("", result,
1587  "", action);
1588  QCoreApplication::postEvent(m_retObject, dce);
1589 }
1590 
1592 {
1593  MythUIType *fw = GetFocusWidget();
1594  if (fw)
1595  {
1596  QString nameClicked = fw->objectName();
1597  int result = 100;
1598  int hashPos = nameClicked.indexOf('#');
1599  if (hashPos > -1)
1600  nameClicked.truncate(hashPos);
1601  if (nameClicked == "INFO")
1602  result=0;
1603  if (nameClicked == "unmute")
1604  nameClicked = "MUTE";
1605  sendResult(result, nameClicked);
1606  }
1607 }
1608 
1609 // Switch to next group of icons. They have to be
1610 // named grp0, grp1, etc with no gaps in numbers.
1612 {
1613  if (m_maxGroupNum <= 0)
1614  return;
1615 
1616  MythUIGroup *group;
1617  UIUtilW::Assign(this, group, QString("grp%1").arg(m_visibleGroup));
1618  group->SetVisible (false);
1619 
1620  // wrap around after last group displayed
1621  if (++m_visibleGroup > m_maxGroupNum)
1622  m_visibleGroup = 0;
1623 
1624  UIUtilW::Assign(this, group, QString("grp%1").arg(m_visibleGroup));
1625  group->SetVisible (true);
1626 }
1627 
1629 {
1630 
1631  char paused = infoMap.value("paused","X").toLocal8Bit().at(0);
1632  if (paused != 'X')
1633  {
1634  if (m_playButton && m_pauseButton && paused != m_paused)
1635  {
1636  MythUIType *fw = GetFocusWidget();
1637  m_playButton->SetVisible(paused=='Y');
1638  m_pauseButton->SetVisible(paused!='Y');
1639  if (fw && (fw == m_playButton || fw == m_pauseButton))
1640  {
1641  fw->LoseFocus();
1642  MythUIType *newfw = (paused=='Y' ? m_playButton : m_pauseButton);
1643  SetFocusWidget(newfw);
1644  if (m_paused == 'X')
1645  newfw->TakeFocus();
1646  }
1647  m_paused = paused;
1648  }
1649  }
1650 
1651  char muted = infoMap.value("muted","X").toLocal8Bit().at(0);
1652  if (m_IsVolumeControl && muted != 'X')
1653  {
1654  if (m_muteButton && m_unMuteButton && muted != m_muted)
1655  {
1656  MythUIType *fw = GetFocusWidget();
1657  m_muteButton->SetVisible(muted!='Y');
1658  m_unMuteButton->SetVisible(muted=='Y');
1659  m_muted = muted;
1660  if (fw && (fw == m_muteButton || fw == m_unMuteButton))
1661  {
1662  fw->LoseFocus();
1663  SetFocusWidget(muted=='Y' ? m_unMuteButton : m_muteButton);
1664  }
1665  }
1666  }
1667 
1669 }
MythPlayer * GetPlayer(void)
Definition: osd.h:205
void DialogSetText(const QString &text)
Definition: osd.cpp:1265
This widget is used for grouping other widgets for display when a particular named state is called.
void DialogShow(const QString &window, const QString &text="", int updatefor=0)
Definition: osd.cpp:1194
QList< MythUIType * > * GetAllChildren(void)
Return a list of all child widgets.
Definition: mythuitype.cpp:219
MythPainter * m_CurrentPainter
Definition: osd.h:219
QString m_PulsedDialogText
Definition: osd.h:224
const AudioOutputGraph & GetAudioGraph() const
Definition: mythplayer.h:190
void SetFontStretch(int stretch)
void SetMessage(const QString &message)
OSDFunctionalType
Definition: osd.h:48
void SetVisible(bool visible) override
void SetImage(MythImage *img)
Should not be used unless absolutely necessary since it bypasses the image caching and threaded loade...
Dialog asking for user confirmation.
TeletextScreen * InitTeletext(void)
Definition: osd.cpp:1297
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
int m_visibleGroup
Definition: osd.h:267
virtual bool keyPressEvent(QKeyEvent *event)
Key event handler.
Definition: mythuitype.cpp:993
void SetBackAction(const QString &text, QVariant data)
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
QRect m_SavedUIRect
Definition: osd.h:233
void SendHideEvent(void)
Definition: osd.cpp:1151
VideoOutput * GetVideoOutput(void)
Definition: mythplayer.h:244
All purpose text widget, displays a text string.
Definition: mythuitext.h:28
void SetText(const InfoMap &map)
Definition: osd.cpp:85
void TeletextReset(void)
Definition: osd.cpp:1363
static void error(const char *str,...)
Definition: vbi.c:41
bool HasWindow(const QString &window)
Definition: osd.cpp:1157
void SetTimeouts(int _short, int _medium, int _long)
Definition: osd.cpp:1039
Image widget, displays a single image or multiple images in sequence.
Definition: mythuiimage.h:97
void Probe()
Definition: osd.cpp:80
bool IsVisible(bool recurse=false) const
Definition: mythuitype.cpp:903
MythUITextEdit * m_channumEdit
Definition: osd.h:97
void TearDown(void)
Definition: osd.cpp:170
void RevertUIScale(void)
Definition: osd.cpp:243
virtual bool Create(void)
void LoseFocus()
Basic menu dialog, message and a list of options.
void ClearSubtitles(void)
Definition: osd.cpp:1432
bool IsVisible(void)
Definition: osd.cpp:283
void DialogQuit(void)
Definition: osd.cpp:1184
QSize GetBaseSize(void) const
QObject * m_retObject
Definition: osd.h:259
QMap< QString, MythScreenType * > m_Children
Definition: osd.h:240
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:168
void SetDisplaying(bool display)
#define OSD_WIN_INTERACT
Definition: osd.h:37
bool TeletextAction(const QString &action)
Definition: osd.cpp:1352
void EnableSubtitles(int type, bool forced_only=false)
bool m_Refresh
Definition: osd.h:226
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:81
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: osd.cpp:105
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QDateTime m_NextPulseUpdate
Definition: osd.h:225
enum OSDFunctionalType m_FunctionalType
Definition: osd.h:237
void GeneralAction(void)
Definition: osd.cpp:1591
virtual QString GetOSDRenderer(void) const
\ brief return OSD renderer type for this videoOutput
void ShowMenu(void) override
Definition: osd.cpp:1576
static MythThemedMenu * menu
void SetGraph(const QString &window, const QString &graph, int64_t timecode)
Definition: osd.cpp:656
void SetPainter(MythPainter *painter)
Definition: mythuitype.h:167
#define OSD_WIN_BDOVERLAY
Definition: osd.h:38
The base class on which all widgets and screens are based.
Definition: mythuitype.h:63
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void BuildFocusList(void)
void DialogBack(QString text="", QVariant data=0, bool exit=false)
Definition: osd.cpp:1272
void SetFunctionalWindow(const QString &window, enum OSDFunctionalType type)
Definition: osd.cpp:1119
void UpdateScreen(MythScreenType *screen)
Will call ::doInit() if the screen is a MythNotificationScreen and ::Create() has been called for it ...
bool m_UIScaleOverride
Definition: osd.h:230
unsigned char r
Definition: ParseText.cpp:340
void GetText(InfoMap &map)
Definition: osd.cpp:97
QRect m_Rect
Definition: osd.h:220
QObject * m_retObject
Definition: osd.h:101
bool gestureEvent(MythGestureEvent *) override
Mouse click/movement handler, receives mouse gesture events from the QCoreApplication event loop.
virtual void End()
Definition: mythpainter.h:51
void Hide(void)
OSDTimeout
Definition: osd.h:59
void AddButton(const QString &title, QVariant data=0, bool newMenu=false, bool setCurrent=false)
bool Create(void) override
Definition: osd.h:120
void sendResult(int result)
Definition: osd.cpp:129
void EnableSubtitles(int type, bool forced_only=false)
Definition: osd.cpp:1416
void SetScalingFactors(float wmult, float hmult)
bool DialogHandleGesture(MythGestureEvent *e)
Definition: osd.cpp:1177
virtual void SetVisible(bool visible)
void DisableForcedSubtitles(void)
bool m_Visible
Definition: osd.h:227
OSD(MythPlayer *player, QObject *parent, MythPainter *painter)
Definition: osd.cpp:153
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
SubtitleScreen * InitSubtitles(void)
Definition: osd.cpp:1383
bool Create(void) override
MythUIButton * m_muteButton
Definition: osd.h:263
bool Create(void) override
Definition: osd.cpp:45
int m_savedFontStretch
Definition: osd.h:235
void SetPainter(MythPainter *painter)
Definition: osd.cpp:200
void SetValues(const QString &window, const QHash< QString, int > &map, OSDTimeout timeout)
Definition: osd.cpp:354
void Confirm()
Definition: osd.cpp:75
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
void SetTextFromMap(const InfoMap &infoMap) override
Definition: osd.cpp:1628
MythUITextEdit * m_xmltvidEdit
Definition: osd.h:99
QDateTime ScreenExpiryTime(const MythScreenType *screen)
Return when the given screen is going to expire will return an invalid QDateTime if screen isn't a My...
int m_FadeTime
Definition: osd.h:222
void DisableForcedSubtitles(void)
Definition: osd.cpp:1423
virtual void SetClipRegion(const QRegion &clipRegion)
Definition: mythpainter.cpp:54
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
Definition: mythuitype.cpp:885
bool Reinit(const QRect &rect, float font_aspect)
Definition: osd.cpp:254
float m_SavedWMult
Definition: osd.h:231
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
void TeletextClear(void)
Definition: osd.cpp:1373
QRegion Draw(MythPainter *painter, QPaintDevice *device, QSize size, QRegion &changed, int alignx=0, int aligny=0)
Definition: osd.cpp:786
bool IsWindowVisible(const QString &window)
Definition: osd.cpp:1047
void More(void)
Definition: osd.cpp:1611
#define OSD_DLG_EDITOR
Definition: osd.h:28
MythUIButton * m_unMuteButton
Definition: osd.h:264
bool ScreenCreated(const MythScreenType *screen)
Return true if ::Create() has been called on screen.
void AddRegion(double start, double end)
bool DialogHandleKeypress(QKeyEvent *e)
Definition: osd.cpp:1170
Create a group of widgets.
Definition: mythuigroup.h:11
void SetReturnEvent(QObject *retobject, const QString &resultid)
MythUITextEdit * m_channameEdit
Definition: osd.h:98
bool DrawDirect(MythPainter *painter, QSize size, bool repaint=false)
Definition: osd.cpp:671
Wrapper around QRect allowing us to handle percentage and other relative values for areas in mythui.
Definition: mythrect.h:17
#define OSD_DLG_NAVIGATE
Definition: osd.h:31
void DisplayBDOverlay(BDOverlay *overlay)
Definition: osd.cpp:1455
void CheckExpiry(void)
Definition: osd.cpp:963
void Reset(void) override
Reset the image back to the default defined in the theme.
static QString GetIcon(uint chanid)
virtual void SetTextFromMap(const InfoMap &infoMap)
void EnableTeletext(bool enable, int page)
Definition: osd.cpp:1334
void SetExpiry(const QString &window, enum OSDTimeout timeout, int custom_timeout=0)
Definition: osd.cpp:1005
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
def log(debug, txt)
Definition: utilities.py:5
virtual void Clear(QPaintDevice *device, const QRegion &region)
Definition: mythpainter.cpp:58
int GetFontStretch(void) const
void SetPage(int page, int subpage)
A custom event that represents a mouse gesture.
Definition: mythgesture.h:39
#define OSD_WIN_TELETEXT
Definition: osd.h:34
const char * name
Definition: ParseText.cpp:339
void RemoveWindow(const QString &window)
Definition: osd.cpp:1073
bool PlayerControlsVolume(void) const
Definition: mythplayer.h:231
void HideAll(bool keepsubs=true, MythScreenType *except=nullptr, bool dropnotification=false)
Definition: osd.cpp:301
MythPlayer * m_parent
Definition: osd.h:217
MythUIHelper * GetMythUI()
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
void DisplayDVDButton(AVSubtitle *dvdButton, QRect &buttonPos)
void SetText(const QString &text, bool moveCursor=true)
MythScreenType * GetWindow(const QString &window)
Definition: osd.cpp:1084
MythUIType * GetFocusWidget(void) const
MythScreenType * m_Dialog
Definition: osd.h:223
void OverrideUIScale(bool log=true)
Definition: osd.cpp:214
A single button widget.
Definition: mythuibutton.h:21
MythMainWindow * GetMythMainWindow(void)
QString m_FunctionalWindow
Definition: osd.h:238
MythUITextEdit * m_callsignEdit
Definition: osd.h:96
void LoadWindows(void)
Definition: osd.cpp:326
void ClearScreen(void)
ChannelEditor(QObject *retobject, const char *name)
Definition: osd.cpp:35
virtual void SetArea(const MythRect &rect)
Definition: mythuitype.cpp:613
void SetUIScreenRect(QRect &rect)
#define kOSDFadeTime
Definition: osd.h:40
bool Create(void) override
bool keyPressEvent(QKeyEvent *) override
Key event handler.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
virtual void Reset(void)
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitype.cpp:92
void DisplayBDOverlay(BDOverlay *overlay)
void GetNotificationScreens(QList< MythScreenType * > &screens)
Return the list of notification screens being currently displayed.
void SetExitAction(const QString &text, QVariant data)
char m_paused
Definition: osd.h:265
float m_SavedHMult
Definition: osd.h:232
void DialogGetText(InfoMap &map)
Definition: osd.cpp:1290
QObject * m_ParentObject
Definition: osd.h:218
bool HasAudioOut(void) const
Definition: mythplayer.h:227
#define OSD_DLG_CONFIRM
Definition: osd.h:32
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
QHash< MythScreenType *, QDateTime > m_ExpireTimes
Definition: osd.h:241
static Type kEventType
Definition: osd.h:76
int m_Timeouts[4]
Definition: osd.h:228
void SetReturnEvent(QObject *retobject, const QString &resultid)
MythImage * GetImage(int64_t timecode) const
void SetText(const QString &window, const InfoMap &map, OSDTimeout timeout)
Definition: osd.cpp:413
void SetText(const QString &text)
bool Create(void) override
Definition: osd.cpp:1482
void SetExpiry1(const QString &window, enum OSDTimeout timeout, int custom_timeout)
Definition: osd.cpp:1019
void HideWindow(const QString &window)
Definition: osd.cpp:1129
bool DisplayState(const QString &name)
MythUIButton * m_playButton
Definition: osd.h:261
void DialogAddButton(QString text, QVariant data, bool menu=false, bool current=false)
Definition: osd.cpp:1283
Definition: osd.h:132
void ResetWindow(const QString &window)
Definition: osd.cpp:1055
static MythUIHelper * getMythUI(void)
void ClearAllSubtitles(void)
QString GetMasterHostPrefix(const QString &storageGroup=QString(), const QString &path=QString())
bool m_IsVolumeControl
Definition: osd.h:269
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
void Display(void)
#define OSD_WIN_SUBTITLE
Definition: osd.h:35
void PositionWindow(MythScreenType *window)
Definition: osd.cpp:1063
bool SetFocusWidget(MythUIType *widget=nullptr)
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: osd.cpp:1537
bool TakeFocus()
int m_maxGroupNum
Definition: osd.h:268
Screen in which all other widgets are contained and rendered.
Progress bar widget.
MythUIButton * m_pauseButton
Definition: osd.h:262
bool KeyPress(const QString &key)
~OSD()
Definition: osd.cpp:165
OsdNavigation(QObject *retobject, const QString &name, OSD *osd)
Definition: osd.cpp:1465
int m_fontStretch
Definition: osd.h:234
bool DialogVisible(QString window=QString())
Definition: osd.cpp:1162
virtual void Begin(QPaintDevice *parent)
Definition: mythpainter.h:50
OSD * m_osd
Definition: osd.h:260
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:37
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:155
void SetEditPosition(double position)
void SetRegions(const QString &window, frm_dir_map_t &map, long long total)
Definition: osd.cpp:589
void ClearRegions(void)
char m_muted
Definition: osd.h:266
#define LOC
Definition: osd.cpp:30
bool m_Effects
Definition: osd.h:221
A narrow purpose widget used to represent cut positions and regions when editing a video.
Definition: mythuieditbar.h:16
bool Init(const QRect &rect, float font_aspect)
Definition: osd.cpp:178
void SetData(QVariant data)
void sendResult(int result, QString action)
Definition: osd.cpp:1581
void GetScreenSettings(float &wmult, float &hmult)
QString GetText(void) const
MythNotificationCenter * GetNotificationCenter(void)
void DisplayDVDButton(AVSubtitle *dvdButton, QRect &pos)
Definition: osd.cpp:1442