MythTV  master
zmliveplayer.cpp
Go to the documentation of this file.
1 /* ============================================================
2  * This program is free software; you can redistribute it
3  * and/or modify it under the terms of the GNU General
4  * Public License as published bythe Free Software Foundation;
5  * either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * ============================================================ */
14 
15 // qt
16 #include <QDateTime>
17 #include <QTimer>
18 #include <QKeyEvent>
19 
20 // myth
21 #include <mythcontext.h>
22 #include <mythuihelper.h>
23 #include <mythmainwindow.h>
24 #include <mythdialogbox.h>
25 
26 // zoneminder
27 #include "zmliveplayer.h"
28 #include "zmclient.h"
29 
30 // the maximum image size we are ever likely to get from ZM
31 #define MAX_IMAGE_SIZE (2048*1536*3)
32 
33 const int FRAME_UPDATE_TIME = 1000 / 10; // try to update the frame 10 times a second
34 
35 ZMLivePlayer::ZMLivePlayer(MythScreenStack *parent, bool isMiniPlayer)
36  :MythScreenType(parent, "zmliveview"),
37  m_frameTimer(new QTimer(this)),
38  m_isMiniPlayer(isMiniPlayer)
39 {
41 
44 
45  connect(m_frameTimer, SIGNAL(timeout()), this,
46  SLOT(updateFrame()));
47 }
48 
50 {
51  // Load the theme for this screen
52  QString winName = m_isMiniPlayer ? "miniplayer" : "zmliveplayer";
53 
54  if (!LoadWindowFromXML("zoneminder-ui.xml", winName, this))
55  {
56  LOG(VB_GENERAL, LOG_ERR, QString("Cannot load screen '%1'").arg(winName));
57  return false;
58  }
59 
60  if (!hideAll())
61  return false;
62 
63  if (m_isMiniPlayer)
64  {
65  // we only support the single camera layout in the mini player
66  if (!initMonitorLayout(1))
67  return false;
68  }
69  else
70  {
71  if (!initMonitorLayout(gCoreContext->GetNumSetting("ZoneMinderLiveLayout", 1)))
72  return false;
73  }
74 
75  return true;
76 }
77 
78 MythUIType* ZMLivePlayer::GetMythUIType(const QString &name, bool optional)
79 {
80  MythUIType *type = GetChild(name);
81 
82  if (!optional && !type)
83  throw name;
84 
85  return type;
86 }
87 
89 {
90  try
91  {
92  // one player layout
93  GetMythUIType("name1-1")->SetVisible(false);
94  GetMythUIType("status1-1")->SetVisible(false);
95  GetMythUIType("frame1-1")->SetVisible(false);
96 
97  if (!m_isMiniPlayer)
98  {
99  // two player layout
100  for (int x = 1; x < 3; x++)
101  {
102  GetMythUIType(QString("name2-%1").arg(x))->SetVisible(false);
103  GetMythUIType(QString("status2-%1").arg(x))->SetVisible(false);
104  GetMythUIType(QString("frame2-%1").arg(x))->SetVisible(false);
105  }
106 
107  // four player layout
108  for (int x = 1; x < 5; x++)
109  {
110  GetMythUIType(QString("name3-%1").arg(x))->SetVisible(false);
111  GetMythUIType(QString("status3-%1").arg(x))->SetVisible(false);
112  GetMythUIType(QString("frame3-%1").arg(x))->SetVisible(false);
113  }
114 
115  // six player layout
116  for (int x = 1; x < 7; x++)
117  {
118  GetMythUIType(QString("name4-%1").arg(x))->SetVisible(false);
119  GetMythUIType(QString("status4-%1").arg(x))->SetVisible(false);
120  GetMythUIType(QString("frame4-%1").arg(x))->SetVisible(false);
121  }
122 
123  // eight player layout
124  for (int x = 1; x < 9; x++)
125  {
126  GetMythUIType(QString("name5-%1").arg(x))->SetVisible(false);
127  GetMythUIType(QString("status5-%1").arg(x))->SetVisible(false);
128  GetMythUIType(QString("frame5-%1").arg(x))->SetVisible(false);
129  }
130  }
131  }
132  catch (const QString &name)
133  {
134  LOG(VB_GENERAL, LOG_ERR,
135  QString("Theme is missing a critical theme element ('%1')")
136  .arg(name));
137  return false;
138  }
139 
140  return true;
141 }
142 
144 {
145  // if we haven't got any monitors there's not much we can do so bail out!
146  if (ZMClient::get()->getMonitorCount() == 0)
147  {
148  LOG(VB_GENERAL, LOG_ERR, "Cannot find any monitors. Bailing out!");
149  ShowOkPopup(tr("Can't show live view.") + "\n" +
150  tr("You don't have any monitors defined!"));
151  return false;
152  }
153 
154  setMonitorLayout(layout, true);
156 
157  return true;
158 }
159 
161 {
162  gCoreContext->SaveSetting("ZoneMinderLiveLayout", m_monitorLayout);
163 
166 
167  if (m_players)
168  {
169  QString s = "";
170  for (auto *p : *m_players)
171  {
172  if (s != "")
173  s += ",";
174  s += QString("%1").arg(p->getMonitor()->id);
175  }
176 
177  gCoreContext->SaveSetting("ZoneMinderLiveCameras", s);
178 
179  delete m_players;
180  }
181  else
182  gCoreContext->SaveSetting("ZoneMinderLiveCameras", "");
183 
184  delete m_frameTimer;
185 
187 }
188 
189 bool ZMLivePlayer::keyPressEvent(QKeyEvent *event)
190 {
191  if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(event))
192  return true;
193 
194  QStringList actions;
195  bool handled = GetMythMainWindow()->TranslateKeyPress("TV Playback", event, actions);
196 
197  for (int i = 0; i < actions.size() && !handled; i++)
198  {
199  QString action = actions[i];
200  handled = true;
201 
202  if (action == "PAUSE")
203  {
204  if (m_paused)
205  {
207  m_paused = false;
208  }
209  else
210  {
211  m_frameTimer->stop();
212  m_paused = true;
213  }
214  }
215  else if (action == "INFO" && !m_isMiniPlayer)
216  {
217  changeView();
218  }
219  else if (action == "1" || action == "2" || action == "3" ||
220  action == "4" || action == "5" || action == "6" ||
221  action == "7" || action == "8" || action == "9")
222  changePlayerMonitor(action.toInt());
223  else if (action == "MENU")
224  {
225  ShowMenu();
226  }
227  else
228  handled = false;
229  }
230 
231  if (!handled && MythScreenType::keyPressEvent(event))
232  handled = true;
233 
234  return handled;
235 }
236 
238 {
239  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
240 
241  auto *menuPopup = new MythDialogBox("Menu", popupStack, "mainmenu");
242 
243  if (menuPopup->Create())
244  popupStack->AddScreen(menuPopup);
245 
246  menuPopup->SetReturnEvent(this, "mainmenu");
247 
248  menuPopup->AddButton(tr("Change View"), QVariant::fromValue(QString("VIEW")));
249  menuPopup->AddButton(tr("Change Camera 1"), QVariant::fromValue(QString("CAMERA1")));
250 
251  if (m_monitorLayout > 1)
252  menuPopup->AddButton(tr("Change Camera 2"), QVariant::fromValue(QString("CAMERA2")));
253 
254  if (m_monitorLayout > 2)
255  {
256  menuPopup->AddButton(tr("Change Camera 3"), QVariant::fromValue(QString("CAMERA3")));
257  menuPopup->AddButton(tr("Change Camera 4"), QVariant::fromValue(QString("CAMERA4")));
258  }
259 
260  if (m_monitorLayout > 3)
261  {
262  menuPopup->AddButton(tr("Change Camera 5"), QVariant::fromValue(QString("CAMERA5")));
263  menuPopup->AddButton(tr("Change Camera 6"), QVariant::fromValue(QString("CAMERA6")));
264  }
265 
266  if (m_monitorLayout > 4)
267  {
268  menuPopup->AddButton(tr("Change Camera 7"), QVariant::fromValue(QString("CAMERA7")));
269  menuPopup->AddButton(tr("Change Camera 8"), QVariant::fromValue(QString("CAMERA8")));
270  }
271 }
272 
273 void ZMLivePlayer::customEvent(QEvent *event)
274 {
275  if (event->type() == DialogCompletionEvent::kEventType)
276  {
277  auto *dce = dynamic_cast<DialogCompletionEvent*>(event);
278 
279  // make sure the user didn't ESCAPE out of the menu
280  if ((dce == nullptr) || (dce->GetResult() < 0))
281  return;
282 
283  QString resultid = dce->GetId();
284  QString data = dce->GetData().toString();
285 
286  if (resultid == "mainmenu")
287  {
288  if (data == "VIEW")
289  changeView();
290  else if (data.startsWith("CAMERA"))
291  {
292  data = data.remove("CAMERA");
293  int monitor = data.toInt();
294  changePlayerMonitor(monitor);
295  }
296  }
297  }
299 }
300 
302 {
303  m_monitorLayout++;
304  if (m_monitorLayout > 5)
305  m_monitorLayout = 1;
307 }
308 
310 {
311  if (playerNo > (int)m_players->size())
312  return;
313 
314  m_frameTimer->stop();
315 
316  int oldMonID = m_players->at(playerNo - 1)->getMonitor()->id;
317 
318  // find the old monitor ID in the list of available monitors
319  int pos = 0;
320  for (pos = 0; pos < ZMClient::get()->getMonitorCount(); pos++)
321  {
322  Monitor *omon = ZMClient::get()->getMonitorAt(pos);
323  if (oldMonID == omon->id)
324  {
325  break;
326  }
327  }
328 
329  // get the next monitor in the list
330  if (pos != ZMClient::get()->getMonitorCount())
331  pos++;
332 
333  // wrap around to the start if we've reached the end
334  if (pos >= ZMClient::get()->getMonitorCount())
335  pos = 0;
336 
337  Monitor *mon = ZMClient::get()->getMonitorAt(pos);
338 
339  m_players->at(playerNo - 1)->setMonitor(mon);
340  m_players->at(playerNo - 1)->updateCamera();
341 
343 }
344 
346 {
347  static std::array<uint8_t,MAX_IMAGE_SIZE> s_buffer {};
348  m_frameTimer->stop();
349 
350  // get a list of monitor id's that need updating
351  QList<int> monList;
352  for (auto *p : *m_players)
353  {
354  if (!monList.contains(p->getMonitor()->id))
355  monList.append(p->getMonitor()->id);
356  }
357 
358  for (int x = 0; x < monList.count(); x++)
359  {
360  QString status;
361  int frameSize = ZMClient::get()->getLiveFrame(monList[x], status, s_buffer);
362 
363  if (frameSize > 0 && !status.startsWith("ERROR"))
364  {
365  // update each player that is displaying this monitor
366  for (auto *p : *m_players)
367  {
368  if (p->getMonitor()->id == monList[x])
369  {
370  if (p->getMonitor()->status != status)
371  {
372  p->getMonitor()->status = status;
373  p->updateStatus();
374  }
375  p->updateFrame(s_buffer.data());
376  }
377  }
378  }
379  }
380 
382 }
383 
385 {
386  m_frameTimer->stop();
387 }
388 
389 void ZMLivePlayer::setMonitorLayout(int layout, bool restore)
390 {
391  QStringList monList;
392 
393  if (m_alarmMonitor != -1)
394  monList.append(QString::number(m_alarmMonitor));
395  else
396  monList = gCoreContext->GetSetting("ZoneMinderLiveCameras", "").split(",");
397 
398  m_monitorLayout = layout;
399 
400  if (m_players)
401  {
402  stopPlayers();
403  delete m_players;
404  }
405 
406  m_players = new vector<Player *>;
407  m_monitorCount = 1;
408 
409  if (layout == 1)
410  m_monitorCount = 1;
411  else if (layout == 2)
412  m_monitorCount = 2;
413  else if (layout == 3)
414  m_monitorCount = 4;
415  else if (layout == 4)
416  m_monitorCount = 6;
417  else if (layout == 5)
418  m_monitorCount = 8;
419 
420  hideAll();
421 
422  int monitorNo = 1;
423 
424  for (int x = 1; x <= m_monitorCount; x++)
425  {
426  Monitor *monitor = nullptr;
427 
428  if (restore)
429  {
430  if (x <= monList.size())
431  {
432  const QString& s = monList.at(x - 1);
433  int monID = s.toInt();
434 
435  // try to find a monitor that matches the monID
436  monitor = ZMClient::get()->getMonitorByID(monID);
437  }
438  }
439 
440  if (!monitor)
441  monitor = ZMClient::get()->getMonitorAt(monitorNo - 1);
442 
443  MythUIImage *frameImage = dynamic_cast<MythUIImage *> (GetChild(QString("frame%1-%2").arg(layout).arg(x)));
444  MythUIText *cameraText = dynamic_cast<MythUIText *> (GetChild(QString("name%1-%2").arg(layout).arg(x)));
445  MythUIText *statusText = dynamic_cast<MythUIText *> (GetChild(QString("status%1-%2").arg(layout).arg(x)));
446 
447  auto *p = new Player();
448  p->setMonitor(monitor);
449  p->setWidgets(frameImage, statusText, cameraText);
450  p->updateCamera();
451  m_players->push_back(p);
452 
453  monitorNo++;
454  if (monitorNo > ZMClient::get()->getMonitorCount())
455  monitorNo = 1;
456  }
457 
458  updateFrame();
459 }
460 
462 
464 {
465  if (m_rgba)
466  free(m_rgba);
467 }
468 
470 {
471  m_monitor = *mon;
472 
473  if (m_rgba)
474  free(m_rgba);
475 
476  m_rgba = (uchar *) malloc(m_monitor.width * m_monitor.height * 4);
477 }
478 
479 void Player::setWidgets(MythUIImage *image, MythUIText *status, MythUIText *camera)
480 {
481  m_frameImage = image;
482  m_statusText = status;
483  m_cameraText = camera;
484 
485  if (m_frameImage)
486  m_frameImage->SetVisible(true);
487 
488  if (m_statusText)
489  m_statusText->SetVisible(true);
490 
491  if (m_cameraText)
492  m_cameraText->SetVisible(true);
493 }
494 
495 void Player::updateFrame(const unsigned char* buffer)
496 {
497  QImage image(buffer, m_monitor.width, m_monitor.height, QImage::Format_RGB888);
498 
500  img->Assign(image);
501  m_frameImage->SetImage(img);
502  img->DecrRef();
503 }
504 
506 {
507  if (m_statusText)
508  {
509  if (m_monitor.status == "Alarm" || m_monitor.status == "Error")
510  m_statusText->SetFontState("alarm");
511  else if (m_monitor.status == "Alert")
512  m_statusText->SetFontState("alert");
513  else
514  m_statusText->SetFontState("idle");
515 
517  }
518 }
519 
521 {
522  if (m_cameraText)
524 }
MythUIText::SetFontState
void SetFontState(const QString &state)
Definition: mythuitext.cpp:221
ZMLivePlayer::m_isMiniPlayer
bool m_isMiniPlayer
Definition: zmliveplayer.h:95
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
ZMLivePlayer::Create
bool Create(void) override
Definition: zmliveplayer.cpp:49
MythUIImage
Image widget, displays a single image or multiple images in sequence.
Definition: mythuiimage.h:98
DialogCompletionEvent::GetId
QString GetId()
Definition: mythdialogbox.h:52
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:551
ZMLivePlayer::hideAll
bool hideAll()
Definition: zmliveplayer.cpp:88
Monitor::width
int width
Definition: zmdefines.h:117
ZMLivePlayer::m_players
vector< Player * > * m_players
Definition: zmliveplayer.h:93
MythUIHelper::DoRestoreScreensaver
void DoRestoreScreensaver(void)
Definition: mythuihelper.cpp:1393
Monitor::name
QString name
Definition: zmdefines.h:107
Player::m_frameImage
MythUIImage * m_frameImage
Definition: zmliveplayer.h:52
ZMClient::getMonitorCount
int getMonitorCount(void)
Definition: zmclient.cpp:839
ZMLivePlayer::setMonitorLayout
void setMonitorLayout(int layout, bool restore=false)
Definition: zmliveplayer.cpp:389
Monitor::status
QString status
Definition: zmdefines.h:116
MythMainWindow::TranslateKeyPress
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
Definition: mythmainwindow.cpp:1106
MythUIType::GetChild
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:131
MythPainter::GetFormatImage
MythImage * GetFormatImage()
Returns a blank reference counted image in the format required for the Draw functions for this painte...
Definition: mythpainter.cpp:540
DialogCompletionEvent::kEventType
static Type kEventType
Definition: mythdialogbox.h:57
ZMLivePlayer::m_paused
bool m_paused
Definition: zmliveplayer.h:89
mythdialogbox.h
MythScreenStack
Definition: mythscreenstack.h:16
arg
arg(title).arg(filename).arg(doDelete))
ZMLivePlayer::~ZMLivePlayer
~ZMLivePlayer() override
Definition: zmliveplayer.cpp:160
MythUIType::customEvent
void customEvent(QEvent *event) override
Definition: mythuitype.cpp:984
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:45
ZMClient::getMonitorByID
Monitor * getMonitorByID(int monID)
Definition: zmclient.cpp:855
Player::updateStatus
void updateStatus(void)
Definition: zmliveplayer.cpp:505
ZMLivePlayer::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: zmliveplayer.cpp:189
MythUIHelper::DoDisableScreensaver
void DoDisableScreensaver(void)
Definition: mythuihelper.cpp:1384
FRAME_UPDATE_TIME
const int FRAME_UPDATE_TIME
Definition: zmliveplayer.cpp:33
ZMLivePlayer::m_monitorLayout
int m_monitorLayout
Definition: zmliveplayer.h:90
MythMainWindow::PauseIdleTimer
void PauseIdleTimer(bool pause)
Definition: mythmainwindow.cpp:2305
ZMLivePlayer::m_alarmMonitor
int m_alarmMonitor
Definition: zmliveplayer.h:96
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &stackname)
Definition: mythmainwindow.cpp:309
ZMLivePlayer::changeView
void changeView(void)
Definition: zmliveplayer.cpp:301
zmliveplayer.h
MythScreenType::GetFocusWidget
MythUIType * GetFocusWidget(void) const
Definition: mythscreentype.cpp:112
ZMLivePlayer::changePlayerMonitor
void changePlayerMonitor(int playerNo)
Definition: zmliveplayer.cpp:309
zmclient.h
Player::m_statusText
MythUIText * m_statusText
Definition: zmliveplayer.h:53
MythMainWindow::GetCurrentPainter
MythPainter * GetCurrentPainter()
Definition: mythmainwindow.cpp:244
Player::updateCamera
void updateCamera()
Definition: zmliveplayer.cpp:520
hardwareprofile.config.p
p
Definition: config.py:33
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:138
ZMLivePlayer::ZMLivePlayer
ZMLivePlayer(MythScreenStack *parent, bool isMiniPlayer=false)
Definition: zmliveplayer.cpp:35
ZMLivePlayer::initMonitorLayout
bool initMonitorLayout(int layout)
Definition: zmliveplayer.cpp:143
MythImage::DecrRef
int DecrRef(void) override
Decrements reference count and deletes on 0.
Definition: mythimage.cpp:54
Player::m_cameraText
MythUIText * m_cameraText
Definition: zmliveplayer.h:54
ZMClient::get
static ZMClient * get(void)
Definition: zmclient.cpp:38
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:930
ZMLivePlayer::ShowMenu
void ShowMenu() override
Definition: zmliveplayer.cpp:237
ZMLivePlayer::m_frameTimer
QTimer * m_frameTimer
Definition: zmliveplayer.h:88
MythUIType
The base class on which all widgets and screens are based.
Definition: mythuitype.h:64
Player::m_monitor
Monitor m_monitor
Definition: zmliveplayer.h:58
mythuihelper.h
Player::updateFrame
void updateFrame(const uchar *buffer)
Definition: zmliveplayer.cpp:495
MythUIText
All purpose text widget, displays a text string.
Definition: mythuitext.h:29
MythScreenType::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: mythscreentype.cpp:414
Monitor::height
int height
Definition: zmdefines.h:118
XMLParseBase::LoadWindowFromXML
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
Definition: xmlparsebase.cpp:692
Player::setWidgets
void setWidgets(MythUIImage *image, MythUIText *status, MythUIText *camera)
Definition: zmliveplayer.cpp:479
MythImage
Definition: mythimage.h:37
ZMLivePlayer::stopPlayers
void stopPlayers(void)
Definition: zmliveplayer.cpp:384
DialogCompletionEvent
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:42
ZMClient::setIsMiniPlayerEnabled
void setIsMiniPlayerEnabled(bool enabled)
Definition: zmclient.h:67
MythUIText::SetText
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:134
MythUIType::SetVisible
virtual void SetVisible(bool visible)
Definition: mythuitype.cpp:1086
Player::m_rgba
uchar * m_rgba
Definition: zmliveplayer.h:56
mythcontext.h
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:107
build_compdb.action
action
Definition: build_compdb.py:9
MythUIImage::SetImage
void SetImage(MythImage *img)
Should not be used unless absolutely necessary since it bypasses the image caching and threaded loade...
Definition: mythuiimage.cpp:748
ZMLivePlayer::m_monitorCount
int m_monitorCount
Definition: zmliveplayer.h:91
Monitor::id
int id
Definition: zmdefines.h:106
ZMLivePlayer::customEvent
void customEvent(QEvent *event) override
Definition: zmliveplayer.cpp:273
Monitor
Definition: zmdefines.h:100
Player
Definition: zmliveplayer.h:36
ZMClient::getLiveFrame
int getLiveFrame(int monitorID, QString &status, FrameData &buffer)
Definition: zmclient.cpp:739
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:899
MythImage::Assign
void Assign(const QImage &img)
Definition: mythimage.cpp:79
ZMClient::getMonitorAt
Monitor * getMonitorAt(int pos)
Definition: zmclient.cpp:845
GetMythUI
MythUIHelper * GetMythUI()
Definition: mythuihelper.cpp:81
Player::setMonitor
void setMonitor(Monitor *mon)
Definition: zmliveplayer.cpp:469
mythmainwindow.h
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:49
Player::~Player
~Player(void)
Definition: zmliveplayer.cpp:463
ZMLivePlayer::updateFrame
void updateFrame(void)
Definition: zmliveplayer.cpp:345
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:916
ZMLivePlayer::GetMythUIType
MythUIType * GetMythUIType(const QString &name, bool optional=false)
Definition: zmliveplayer.cpp:78