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