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