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