MythTV master
mythplayeroverlayui.cpp
Go to the documentation of this file.
1#include <chrono>
2
3// MythTV
7
8#include "tv_play.h"
9#include "livetvchain.h"
10#include "mythplayeroverlayui.h"
11
12#define LOC QString("PlayerOverlay: ")
13
14// N.B. Overlay is initialised without a player - it must be set before it can be used
16 : MythPlayerUIBase(MainWindow, Tv, Context, Flags),
17 m_osd(MainWindow, Tv, nullptr, m_painter)
18{
19 // Register our state type for signalling
20 qRegisterMetaType<MythOverlayState>();
21
22 m_positionUpdateTimer.setInterval(99ms);
25 connect(m_tv, &TV::ChangeOSDMessage, this, qOverload<const QString&>(&MythPlayerOverlayUI::UpdateOSDMessage));
26
27 // Signalled directly from TV to OSD
29 connect(m_tv, &TV::HideAll, &m_osd, &OSD::HideAll);
31}
32
34{
35 m_browsing = Browsing;
37}
38
40{
41 m_editing = Editing;
43}
44
46{
47 if (Enable)
49 else
51}
52
62{
63 m_osdLock.lock();
65 {
70 }
71 else
72 {
74 }
75 m_osdLock.unlock();
76}
77
78void MythPlayerOverlayUI::UpdateOSDMessage(const QString& Message)
79{
81}
82
83void MythPlayerOverlayUI::UpdateOSDMessage(const QString& Message, OSDTimeout Timeout)
84{
85 m_osdLock.lock();
86 InfoMap map;
87 map.insert("message_text", Message);
88 m_osd.SetText(OSD_WIN_MESSAGE, map, Timeout);
89 m_osdLock.unlock();
90}
91
93{
94 m_osdLock.lock();
97 info.text.insert("title", title);
100 m_osdLock.unlock();
101}
102
104{
105 m_osdLock.lock();
107 m_osd.SetValues(OSD_WIN_STATUS, Info.values, Timeout);
108 m_osd.SetText(OSD_WIN_STATUS, Info.text, Timeout);
109 if (Type != kOSDFunctionalType_Default)
111 m_osdLock.unlock();
112}
113
114void MythPlayerOverlayUI::UpdateOSDStatus(const QString& Title, const QString& Desc,
115 const QString& Value, int Type, const QString& Units,
116 int Position, OSDTimeout Timeout)
117{
119 info.values.insert("position", Position);
120 info.values.insert("relposition", Position);
121 info.text.insert("title", Title);
122 info.text.insert("description", Desc);
123 info.text.insert("value", Value);
124 info.text.insert("units", Units);
125 UpdateOSDStatus(info, Type, Timeout);
126}
127
128void MythPlayerOverlayUI::UpdateSliderInfo(osdInfo &Info, bool PaddedFields)
129{
130 if (!m_decoder)
131 return;
132
133 bool islive = false;
134 Info.text.insert("chapteridx", QString());
135 Info.text.insert("totalchapters", QString());
136 Info.text.insert("titleidx", QString());
137 Info.text.insert("totaltitles", QString());
138 Info.text.insert("angleidx", QString());
139 Info.text.insert("totalangles", QString());
140 Info.values.insert("position", 0);
141 Info.values.insert("progbefore", 0);
142 Info.values.insert("progafter", 0);
143
144 std::chrono::seconds playbackLen = 0s;
145 bool fixed_playbacklen = false;
146
148 {
149 Info.values["progbefore"] = static_cast<int>(m_playerCtx->m_tvchain->HasPrev());
150 Info.values["progafter"] = static_cast<int>(m_playerCtx->m_tvchain->HasNext());
151 playbackLen = m_playerCtx->m_tvchain->GetLengthAtCurPos();
152 islive = true;
153 fixed_playbacklen = true;
154 }
155 else if (IsWatchingInprogress())
156 {
157 islive = true;
158 }
159 else
160 {
161 int chapter = GetCurrentChapter();
162 int chapters = GetNumChapters();
163 if (chapter && chapters > 1)
164 {
165 Info.text["chapteridx"] = QString::number(chapter + 1);
166 Info.text["totalchapters"] = QString::number(chapters);
167 }
168
169 int title = GetCurrentTitle();
170 int titles = GetNumTitles();
171 if (title && titles > 1)
172 {
173 Info.text["titleidx"] = QString::number(title + 1);
174 Info.text["totaltitles"] = QString::number(titles);
175 }
176
177 int angle = GetCurrentAngle();
178 int angles = GetNumAngles();
179 if (angle && angles > 1)
180 {
181 Info.text["angleidx"] = QString::number(angle + 1);
182 Info.text["totalangles"] = QString::number(angles);
183 }
184 }
185
186 // Set the raw values, followed by the translated values.
187 for (int i = 0; i < 2 ; ++i)
188 {
189 bool honorCutList = (i > 0);
190 bool stillFrame = false;
191 int pos = 0;
192
193 QString relPrefix = (honorCutList ? "rel" : "");
194 if (!fixed_playbacklen)
195 playbackLen = GetTotalSeconds(honorCutList);
196 std::chrono::seconds secsplayed = GetSecondsPlayed(honorCutList);
197
198 stillFrame = (secsplayed < 0s);
199 playbackLen = std::max(playbackLen, 0s);
200 secsplayed = std::clamp(secsplayed, 0s, playbackLen);
201 std::chrono::seconds secsbehind = std::max((playbackLen - secsplayed), 0s);
202
203 if (playbackLen > 0s)
204 pos = static_cast<int>(1000.0F * secsplayed.count() / playbackLen.count());
205
206 Info.values.insert(relPrefix + "secondsplayed", static_cast<int>(secsplayed.count()));
207 Info.values.insert(relPrefix + "totalseconds", static_cast<int>(playbackLen.count()));
208 Info.values[relPrefix + "position"] = pos;
209
210 QString text1;
211 QString text2;
212 QString text3;
213 if (PaddedFields)
214 {
215 text1 = MythDate::formatTime(secsplayed, "HH:mm:ss");
216 text2 = MythDate::formatTime(playbackLen, "HH:mm:ss");
217 text3 = MythDate::formatTime(secsbehind, "HH:mm:ss");
218 }
219 else
220 {
221 QString fmt = (playbackLen >= 1h) ? "H:mm:ss" : "m:ss";
222 text1 = MythDate::formatTime(secsplayed, fmt);
223 text2 = MythDate::formatTime(playbackLen, fmt);
224
225 if (secsbehind >= 1h)
226 text3 = MythDate::formatTime(secsbehind, "H:mm:ss");
227 else if (secsbehind >= 1min)
228 text3 = MythDate::formatTime(secsbehind, "m:ss");
229 else
230 text3 = tr("%n second(s)", "", static_cast<int>(secsbehind.count()));
231 }
232
233 QString desc = stillFrame ? tr("Still Frame") : tr("%1 of %2").arg(text1, text2);
234 Info.text[relPrefix + "description"] = desc;
235 Info.text[relPrefix + "playedtime"] = text1;
236 Info.text[relPrefix + "totaltime"] = text2;
237 Info.text[relPrefix + "remainingtime"] = islive ? QString() : text3;
238 Info.text[relPrefix + "behindtime"] = islive ? text3 : QString();
239 QString dtformat = gCoreContext->GetSetting("DateFormat", "ddd MMMM d yyyy")
240 + ", " + gCoreContext->GetSetting("TimeFormat", "hh:mm");
241
244 {
245 QDateTime recordedtime =
246 m_playerCtx->m_playingRecStart.addSecs(static_cast<qint64>(secsplayed.count()));
247 Info.text[relPrefix + "recordedtime"] = recordedtime.toLocalTime().toString(dtformat);
248 }
249
250 if (i == 0)
251 {
252 LOG(VB_OSD, LOG_INFO, LOC +
253 QString(" playbackLen:%1").arg(playbackLen.count()) +
254 QString(" secsplayed:%1").arg(secsplayed.count()));
255 }
256 }
257}
258
259std::chrono::milliseconds MythPlayerOverlayUI::GetMillisecondsPlayed(bool HonorCutList)
260{
261 std::chrono::milliseconds pos = TranslatePositionFrameToMs(m_framesPlayed, HonorCutList);
262 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("GetSecondsPlayed: framesPlayed %1, honorCutList %2, pos %3")
263 .arg(m_framesPlayed).arg(HonorCutList).arg(pos.count()));
264 return pos;
265}
266
267std::chrono::seconds MythPlayerOverlayUI::GetSecondsPlayed(bool HonorCutList)
268{
269 return duration_cast<std::chrono::seconds>(GetMillisecondsPlayed(HonorCutList));
270}
271
272std::chrono::milliseconds MythPlayerOverlayUI::GetTotalMilliseconds(bool HonorCutList) const
273{
274 uint64_t pos = IsWatchingInprogress() ? UINT64_MAX : m_totalFrames;
275 return TranslatePositionFrameToMs(pos, HonorCutList);
276}
277
278std::chrono::seconds MythPlayerOverlayUI::GetTotalSeconds(bool HonorCutList) const
279{
280 return duration_cast<std::chrono::seconds>(GetTotalMilliseconds(HonorCutList));
281}
282
283
bool HasNext(void) const
bool HasPrev(void) const
Definition: livetvchain.h:62
std::chrono::seconds GetLengthAtCurPos(void)
QString GetSetting(const QString &key, const QString &defaultval="")
virtual void UpdateSliderInfo(osdInfo &Info, bool PaddedFields=false)
void ChangeOSDPositionUpdates(bool Enable)
std::chrono::seconds GetSecondsPlayed(bool HonorCutList)
void OverlayStateChanged(MythOverlayState OverlayState)
std::chrono::seconds GetTotalSeconds(bool HonorCutList) const
virtual std::chrono::milliseconds GetTotalMilliseconds(bool HonorCutList) const
virtual std::chrono::milliseconds GetMillisecondsPlayed(bool HonorCutList)
void UpdateOSDPosition()
Update the OSD status/position window.
void UpdateOSDMessage(const QString &Message)
MythPlayerOverlayUI(MythMainWindow *MainWindow, TV *Tv, PlayerContext *Context, PlayerFlags Flags)
void SetOSDStatus(const QString &Title, OSDTimeout Timeout)
void EditingChanged(bool Editing)
void BrowsingChanged(bool Browsing)
void UpdateOSDStatus(osdInfo &Info, int Type, OSDTimeout Timeout)
QRecursiveMutex m_osdLock
virtual int GetNumAngles(void) const
Definition: mythplayer.h:224
bool m_liveTV
Definition: mythplayer.h:403
virtual int GetNumTitles(void) const
Definition: mythplayer.h:218
DecoderBase * m_decoder
Definition: mythplayer.h:362
virtual int GetCurrentAngle(void) const
Definition: mythplayer.h:225
virtual int GetNumChapters(void)
uint64_t m_framesPlayed
Definition: mythplayer.h:424
virtual int GetCurrentTitle(void) const
Definition: mythplayer.h:219
uint64_t m_totalFrames
Definition: mythplayer.h:425
virtual int GetCurrentChapter(void)
bool IsWatchingInprogress(void) const
Definition: mythplayer.cpp:127
PlayerContext * m_playerCtx
Definition: mythplayer.h:366
std::chrono::milliseconds TranslatePositionFrameToMs(uint64_t position, bool use_cutlist) const
void SetValues(const QString &Window, const QHash< QString, int > &Map, OSDTimeout Timeout)
Definition: osd.cpp:152
void ResetWindow(const QString &Window)
Definition: osd.cpp:636
void SetFunctionalWindow(const QString &Window, enum OSDFunctionalType Type)
Definition: osd.cpp:667
bool IsWindowVisible(const QString &Window)
Definition: osd.cpp:628
void Embed(bool Embedding)
Definition: osd.cpp:78
void SetText(const QString &Window, const InfoMap &Map, OSDTimeout Timeout)
Definition: osd.cpp:210
void HideAll(bool KeepSubs=true, MythScreenType *Except=nullptr, bool DropNotification=false)
Definition: osd.cpp:95
void DialogQuit()
Definition: osd.cpp:720
TVState GetState(void) const
QDateTime m_playingRecStart
LiveTVChain * m_tvchain
void HideAll(bool KeepSubs=true, MythScreenType *Except=nullptr, bool DropNotification=false)
void EmbedPlayback(bool Embed, const QRect &Rect={})
void OverlayStateChanged(MythOverlayState OverlayState)
void ChangeOSDMessage(const QString &Message)
Control TV playback.
Definition: tv_play.h:156
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
PlayerFlags
Definition: mythplayer.h:65
#define LOC
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
QString formatTime(std::chrono::milliseconds msecs, QString fmt)
Format a milliseconds time value.
Definition: mythdate.cpp:242
dictionary info
Definition: azlyrics.py:7
static constexpr const char * OSD_WIN_STATUS
Definition: osd.h:32
OSDFunctionalType
Definition: osd.h:45
@ kOSDFunctionalType_Default
Definition: osd.h:46
OSDTimeout
Definition: osd.h:56
@ kOSDTimeout_Ignore
Definition: osd.h:57
@ kOSDTimeout_Med
Definition: osd.h:60
static constexpr const char * OSD_WIN_MESSAGE
Definition: osd.h:29
static eu8 clamp(eu8 value, eu8 low, eu8 high)
Definition: pxsup2dast.c:206
QHash< QString, int > values
Definition: playercontext.h:37
InfoMap text
Definition: playercontext.h:36
@ kState_WatchingPreRecorded
Watching Pre-recorded is a TV only state for when we are watching a pre-existing recording.
Definition: tv.h:70
@ kState_WatchingRecording
Watching Recording is the state for when we are watching an in progress recording,...
Definition: tv.h:83