MythTV  master
zmplayer.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 // C++
16 #include <chrono>
17 #include <cstdlib>
18 #include <iostream>
19 
20 // Qt
21 #include <QKeyEvent>
22 #include <QTimer>
23 
24 // MythTV
25 #include <libmyth/mythcontext.h>
26 #include <libmythbase/mythdate.h>
27 #include <libmythbase/mythdbcon.h>
29 #include <libmythui/mythuihelper.h>
30 
31 // zoneminder
32 #include "zmclient.h"
33 #include "zmplayer.h"
34 
35 ZMPlayer::ZMPlayer(MythScreenStack *parent, const char *name,
36  std::vector<Event *> *eventList, size_t *currentEvent)
37  :MythScreenType(parent, name),
38  m_currentEvent(currentEvent),
39  m_eventList(eventList), m_frameList(new std::vector<Frame*>),
40  m_frameTimer(new QTimer(this))
41 {
42  connect(m_frameTimer, &QTimer::timeout, this,
44 }
45 
47 {
48  stopPlayer();
49 
50  m_frameTimer->deleteLater();
51 
52  delete m_frameList;
53 }
54 
56 {
57  m_frameTimer->stop();
58 }
59 
60 bool ZMPlayer::Create(void)
61 {
62  // Load the theme for this screen
63  bool foundtheme = LoadWindowFromXML("zoneminder-ui.xml", "zmplayer", this);
64  if (!foundtheme)
65  return false;
66 
67  bool err = false;
68 
69  UIUtilE::Assign(this, m_frameImageFS, "framefsimage", &err);
70  UIUtilE::Assign(this, m_frameImage, "frameimage", &err);
71  UIUtilE::Assign(this, m_noEventsText, "noevents_text", &err);
72  UIUtilE::Assign(this, m_eventText, "event_text", &err);
73  UIUtilE::Assign(this, m_cameraText, "camera_text", &err);
74  UIUtilE::Assign(this, m_frameText, "frame_text", &err);
75  UIUtilE::Assign(this, m_dateText, "date_text", &err);
76 
77  UIUtilW::Assign(this, m_playButton, "play_button");
78  UIUtilW::Assign(this, m_deleteButton, "delete_button");
79  UIUtilW::Assign(this, m_prevButton, "prev_button");
80  UIUtilW::Assign(this, m_nextButton, "next_button");
81 
82  if (err)
83  {
84  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'zmplayer'");
85  return false;
86  }
87 
88  if (m_playButton)
89  {
90  m_playButton->SetText(tr("Pause"));
92  }
93 
94  if (m_deleteButton)
95  {
96  m_deleteButton->SetText(tr("Delete"));
98  }
99 
100  if (m_prevButton)
101  {
102  m_prevButton->SetText(tr("Previous"));
104  }
105 
106  if (m_nextButton)
107  {
108  m_nextButton->SetText(tr("Next"));
110  }
111 
112  // hide the fullscreen image
113  m_frameImageFS->SetVisible(false);
115 
116  BuildFocusList();
117 
119 
120  getEventInfo();
121 
122  return true;
123 }
124 
126 {
127  m_frameTimer->stop();
128 
129  if (*m_currentEvent == static_cast<size_t>(-1))
130  {
131  stopPlayer();
132 
133  if (m_noEventsText)
134  m_noEventsText->SetVisible(true);
135 
136  m_activeFrameImage->SetFilename(QString("mz_black.png"));
138 
139  m_eventText->Reset();
140  m_cameraText->Reset();
141  m_frameText->Reset();
142  m_dateText->Reset();
143 
144  return;
145  }
146 
147  if (m_noEventsText)
148  m_noEventsText->SetVisible(false);
149 
150  Event *event = m_eventList->at(*m_currentEvent);
151  if (!event)
152  return;
153 
154  m_curFrame = 1;
155 
156  m_eventText->SetText(event->eventName() + QString(" (%1/%2)")
157  .arg((*m_currentEvent) + 1)
158  .arg(m_eventList->size()));
159  m_cameraText->SetText(event->monitorName());
162  event->startTime(),
164 
165  // get frames data
166  m_frameList->clear();
167  if (class ZMClient *zm = ZMClient::get())
168  {
169  zm->getFrameList(event->eventID(), m_frameList);
170  m_frameText->SetText(QString("%1/%2").arg(m_curFrame).arg(m_frameList->size()));
171  getFrame();
172  }
173 }
174 
175 bool ZMPlayer::keyPressEvent(QKeyEvent *event)
176 {
177  if (GetFocusWidget()->keyPressEvent(event))
178  return true;
179 
180  QStringList actions;
181  bool handled = GetMythMainWindow()->TranslateKeyPress("TV Playback", event, actions);
182 
183  for (int i = 0; i < actions.size() && !handled; i++)
184  {
185  QString action = actions[i];
186  handled = true;
187 
188  if (action == "PAUSE")
189  {
190  if (m_playButton)
191  m_playButton->Push();
192  }
193  else if (action == "DELETE")
194  {
195  if (m_deleteButton)
196  m_deleteButton->Push();
197  }
198  else if (action == "LEFT")
199  {
200  if (m_paused)
201  {
202  if (m_curFrame > 1)
203  m_curFrame--;
204  getFrame();
205  }
206  }
207  else if (action == "RIGHT")
208  {
209  if (m_paused)
210  {
211  if (m_curFrame < m_frameList->size())
212  m_curFrame++;
213  getFrame();
214  }
215  }
216  else if (action == "PAGEUP")
217  {
218  if (m_prevButton)
219  m_prevButton->Push();
220  }
221  else if (action == "PAGEDOWN")
222  {
223  if (m_nextButton)
224  m_nextButton->Push();
225  }
226  else if (action == "TOGGLEASPECT" || action == "TOGGLEFILL")
227  {
228  if (!m_eventList->empty())
229  {
230  stopPlayer();
231 
232  if (m_fullScreen)
233  {
234  m_fullScreen = false;
235  m_frameImage->SetVisible(false);
236  m_frameImageFS->SetVisible(true);
238  }
239  else
240  {
241  m_fullScreen = true;
242  m_frameImageFS->SetVisible(false);
243  m_frameImage->SetVisible(true);
245  }
246 
247  if (!m_paused)
248  m_frameTimer->start(10ms);
249 
250  }
251  }
252  else
253  handled = false;
254  }
255 
256  if (!handled && MythScreenType::keyPressEvent(event))
257  handled = true;
258 
259  return handled;
260 }
261 
263 {
264  if (m_eventList->empty())
265  return;
266 
267  if (m_paused)
268  {
269  m_frameTimer->start(40ms);
270  m_paused = false;
271  if (m_playButton)
272  m_playButton->SetText(tr("Pause"));
273  }
274  else
275  {
276  m_frameTimer->stop();
277  m_paused = true;
278  if (m_playButton)
279  m_playButton->SetText(tr("Play"));
280  }
281 }
282 
284 {
285  if (m_eventList->empty() || (*m_currentEvent > m_eventList->size() - 1))
286  return;
287 
288  Event *event = m_eventList->at(*m_currentEvent);
289  if (event)
290  {
291  m_frameTimer->stop();
292 
293  if (class ZMClient *zm = ZMClient::get())
294  zm->deleteEvent(event->eventID());
295 
296  m_eventList->erase(m_eventList->begin() + *m_currentEvent);
297  if (*m_currentEvent > (m_eventList->size() - 1))
298  *m_currentEvent = (m_eventList->size() - 1);
299 
300  getEventInfo();
301 
302  if (!m_eventList->empty())
303  {
304  m_frameTimer->start(40ms);
305  m_paused = false;
306  }
307  }
308 }
309 
311 {
312  if (m_eventList->empty())
313  return;
314 
315  if (*m_currentEvent >= (m_eventList->size() - 1))
316  return;
317 
318  (*m_currentEvent)++;
319 
320  getEventInfo();
321 
322  if (m_paused)
323  playPressed();
324 }
325 
327 {
328  if (m_eventList->empty())
329  return;
330 
331  if (*m_currentEvent == 0)
332  return;
333 
334  if (*m_currentEvent > m_eventList->size())
335  *m_currentEvent = m_eventList->size();
336 
337  (*m_currentEvent)--;
338 
339  getEventInfo();
340 
341  if (m_paused)
342  playPressed();
343 }
344 
346 {
347  if (m_frameList->empty())
348  return;
349 
350  m_frameTimer->stop();
351 
352  m_curFrame++;
353  if (m_curFrame > m_frameList->size())
354  {
355  m_paused = true;
356  m_curFrame = 1;
357  if (m_playButton)
358  m_playButton->SetText(tr("Play"));
359  return;
360  }
361 
362  getFrame();
363 }
364 
366 {
367  if (m_eventList->empty())
368  return;
369 
370  Event *event = m_eventList->at(*m_currentEvent);
371  if (event)
372  {
373  if (class ZMClient *zm = ZMClient::get())
374  zm->getEventFrame(event, m_curFrame, &m_image);
375 
376  if (m_image)
377  {
379  m_frameText->SetText(QString("%1/%2").arg(m_curFrame).arg(m_frameList->size()));
380  }
381 
382  if (!m_paused)
383  {
384  if (m_curFrame < m_frameList->size())
385  {
386  double delta = m_frameList->at(m_curFrame)->delta -
387  m_frameList->at(m_curFrame - 1)->delta;
388 
389  // FIXME: this is a bit of a hack to try to not swamp the cpu
390  if (delta < 0.1)
391  delta = 0.1;
392 
393  m_frameTimer->start((int) (1000 * delta));
394  }
395  else
396  m_frameTimer->start(10ms);
397  }
398  }
399 }
MythUIButton::Clicked
void Clicked()
ZMPlayer::m_noEventsText
MythUIText * m_noEventsText
Definition: zmplayer.h:62
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:84
ZMPlayer::m_frameImage
MythUIImage * m_frameImage
Definition: zmplayer.h:60
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
ZMPlayer::deletePressed
void deletePressed(void)
Definition: zmplayer.cpp:283
ZMPlayer::stopPlayer
void stopPlayer(void)
Definition: zmplayer.cpp:55
MythUIText::Reset
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitext.cpp:82
ZMPlayer::m_eventText
MythUIText * m_eventText
Definition: zmplayer.h:63
ZMPlayer::m_dateText
MythUIText * m_dateText
Definition: zmplayer.h:66
ZMPlayer::prevPressed
void prevPressed(void)
Definition: zmplayer.cpp:326
MythUIImage::Load
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
Definition: mythuiimage.cpp:968
Frame
Definition: zmdefines.h:93
ZMPlayer::Create
bool Create(void) override
Definition: zmplayer.cpp:60
ZMPlayer::m_activeFrameImage
MythUIImage * m_activeFrameImage
Definition: zmplayer.h:58
MythScreenStack
Definition: mythscreenstack.h:16
mythdbcon.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:45
ZMPlayer::m_prevButton
MythUIButton * m_prevButton
Definition: zmplayer.h:71
ZMPlayer::m_currentEvent
size_t * m_currentEvent
Definition: zmplayer.h:73
ZMPlayer::m_fullScreen
bool m_fullScreen
Definition: zmplayer.h:81
MythScreenType::GetFocusWidget
MythUIType * GetFocusWidget(void) const
Definition: mythscreentype.cpp:113
zmclient.h
ZMPlayer::m_nextButton
MythUIButton * m_nextButton
Definition: zmplayer.h:70
mythdate.h
MythMainWindow::TranslateKeyPress
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
Definition: mythmainwindow.cpp:1104
ZMPlayer::m_frameText
MythUIText * m_frameText
Definition: zmplayer.h:65
ZMPlayer::playPressed
void playPressed(void)
Definition: zmplayer.cpp:262
Event
Event details.
Definition: zmdefines.h:26
MythScreenType::SetFocusWidget
bool SetFocusWidget(MythUIType *widget=nullptr)
Definition: mythscreentype.cpp:118
ZMPlayer::updateFrame
void updateFrame(void)
Definition: zmplayer.cpp:345
MythUIButton::SetText
void SetText(const QString &msg)
Definition: mythuibutton.cpp:227
ZMPlayer::~ZMPlayer
~ZMPlayer() override
Definition: zmplayer.cpp:46
MythScreenType::BuildFocusList
void BuildFocusList(void)
Definition: mythscreentype.cpp:206
ZMPlayer::nextPressed
void nextPressed(void)
Definition: zmplayer.cpp:310
ZMPlayer::m_paused
bool m_paused
Definition: zmplayer.h:80
MythUIButton::Push
void Push(bool lock=false)
Definition: mythuibutton.cpp:173
ZMPlayer::m_curFrame
uint m_curFrame
Definition: zmplayer.h:78
ZMPlayer::ZMPlayer
ZMPlayer(MythScreenStack *parent, const char *name, std::vector< Event * > *eventList, size_t *currentEvent)
Definition: zmplayer.cpp:35
ZMClient::get
static ZMClient * get(void)
Definition: zmclient.cpp:37
zmplayer.h
ZMPlayer::m_cameraText
MythUIText * m_cameraText
Definition: zmplayer.h:64
UIUtilDisp::Assign
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
ZMPlayer::getEventInfo
void getEventInfo(void)
Definition: zmplayer.cpp:125
MythDate::kSimplify
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:26
mythuihelper.h
MythScreenType::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: mythscreentype.cpp:404
XMLParseBase::LoadWindowFromXML
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
Definition: xmlparsebase.cpp:695
ZMPlayer::m_deleteButton
MythUIButton * m_deleteButton
Definition: zmplayer.h:69
std
Definition: mythchrono.h:23
MythUIText::SetText
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:132
MythUIType::SetVisible
virtual void SetVisible(bool visible)
Definition: mythuitype.cpp:1108
mythcontext.h
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:102
ZMPlayer::m_frameList
std::vector< Frame * > * m_frameList
Definition: zmplayer.h:76
ZMPlayer::m_image
MythImage * m_image
Definition: zmplayer.h:83
build_compdb.action
action
Definition: build_compdb.py:9
ZMPlayer::getFrame
void getFrame(void)
Definition: zmplayer.cpp:365
ZMPlayer::m_frameTimer
QTimer * m_frameTimer
Definition: zmplayer.h:77
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
MythDate::kDateTimeFull
@ kDateTimeFull
Default local time.
Definition: mythdate.h:23
ZMPlayer::m_eventList
std::vector< Event * > * m_eventList
Definition: zmplayer.h:74
MythUIImage::SetFilename
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
Definition: mythuiimage.cpp:676
ZMPlayer::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: zmplayer.cpp:175
mythmainwindow.h
ZMPlayer::m_playButton
MythUIButton * m_playButton
Definition: zmplayer.h:68
ZMPlayer::m_frameImageFS
MythUIImage * m_frameImageFS
Definition: zmplayer.h:59
ZMClient
Definition: zmclient.h:19