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
31
32// zoneminder
33#include "zmclient.h"
34#include "zmplayer.h"
35
36ZMPlayer::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
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
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
116
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)
136
137 m_activeFrameImage->SetFilename(QString("mz_black.png"));
139
143 m_dateText->Reset();
144
145 return;
146 }
147
148 if (m_noEventsText)
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
176bool 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)
193 }
194 else if (action == "DELETE")
195 {
196 if (m_deleteButton)
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)
221 }
222 else if (action == "PAGEDOWN")
223 {
224 if (m_nextButton)
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);
239 }
240 else
241 {
242 m_fullScreen = 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}
Event details.
Definition: zmdefines.h:28
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
Screen in which all other widgets are contained and rendered.
void BuildFocusList(void)
MythUIType * GetFocusWidget(void) const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool SetFocusWidget(MythUIType *widget=nullptr)
void SetText(const QString &msg)
void Push(bool lock=false)
void Clicked()
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
void SetImage(MythImage *img)
Should not be used unless absolutely necessary since it bypasses the image caching and threaded loade...
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitext.cpp:65
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:115
virtual void SetVisible(bool visible)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
static ZMClient * get(void)
Definition: zmclient.cpp:37
MythImage * m_image
Definition: zmplayer.h:83
MythUIText * m_noEventsText
Definition: zmplayer.h:62
void stopPlayer(void)
Definition: zmplayer.cpp:56
std::vector< Frame * > * m_frameList
Definition: zmplayer.h:76
MythUIImage * m_activeFrameImage
Definition: zmplayer.h:58
MythUIText * m_dateText
Definition: zmplayer.h:66
bool Create(void) override
Definition: zmplayer.cpp:61
MythUIButton * m_prevButton
Definition: zmplayer.h:71
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: zmplayer.cpp:176
void updateFrame(void)
Definition: zmplayer.cpp:346
std::vector< Event * > * m_eventList
Definition: zmplayer.h:74
void nextPressed(void)
Definition: zmplayer.cpp:312
void getEventInfo(void)
Definition: zmplayer.cpp:126
bool m_fullScreen
Definition: zmplayer.h:81
void playPressed(void)
Definition: zmplayer.cpp:265
uint m_curFrame
Definition: zmplayer.h:78
~ZMPlayer() override
Definition: zmplayer.cpp:47
MythUIText * m_frameText
Definition: zmplayer.h:65
MythUIText * m_eventText
Definition: zmplayer.h:63
QTimer * m_frameTimer
Definition: zmplayer.h:77
MythUIImage * m_frameImageFS
Definition: zmplayer.h:59
MythUIButton * m_nextButton
Definition: zmplayer.h:70
MythUIText * m_cameraText
Definition: zmplayer.h:64
void deletePressed(void)
Definition: zmplayer.cpp:286
MythUIButton * m_playButton
Definition: zmplayer.h:68
ZMPlayer(MythScreenStack *parent, const char *name, std::vector< Event * > *eventList, size_t *currentEvent)
Definition: zmplayer.cpp:36
bool m_paused
Definition: zmplayer.h:80
MythUIButton * m_deleteButton
Definition: zmplayer.h:69
MythUIImage * m_frameImage
Definition: zmplayer.h:60
void getFrame(void)
Definition: zmplayer.cpp:366
void prevPressed(void)
Definition: zmplayer.cpp:328
size_t * m_currentEvent
Definition: zmplayer.h:73
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
@ kDateTimeFull
Default local time.
Definition: mythdate.h:23
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:26
STL namespace.
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27