MythTV master
welcomedialog.cpp
Go to the documentation of this file.
1// POSIX
2#include <unistd.h>
3
4// C++
5#include <chrono>
6#include <cstdlib>
7#include <thread>
8
9// qt
10#include <QtGlobal>
11#if QT_VERSION >= QT_VERSION_CHECK(6,5,0)
12#include <QtSystemDetection>
13#endif
14#include <QEvent>
15#include <QGuiApplication>
16#include <QKeyEvent>
17
18// myth
19#include "libmythbase/compat.h"
27#include "libmythtv/tv.h"
28
29// mythwelcome
30#include "welcomedialog.h"
31#include "welcomesettings.h"
32
33static constexpr std::chrono::milliseconds UPDATE_STATUS_INTERVAL { 30s };
34static constexpr std::chrono::milliseconds UPDATE_SCREEN_INTERVAL { 15s };
35
36
38 :MythScreenType(parent, name),
39 m_updateStatusTimer(new QTimer(this)),
40 m_updateScreenTimer(new QTimer(this))
41{
43
45 m_preRollSeconds = gCoreContext->GetDurSetting<std::chrono::seconds>("RecordPreRoll");
47 gCoreContext->GetDurSetting<std::chrono::minutes>("idleWaitForRecordingTime", 15min);
48 m_idleTimeoutSecs = gCoreContext->GetDurSetting<std::chrono::seconds>("idleTimeoutSecs", 0s);
49
50 // if idleTimeoutSecs is 0, the user disabled the auto-shutdown feature
52
56
59}
60
62{
63 // Load the theme for this screen
64 bool foundtheme = LoadWindowFromXML("welcome-ui.xml", "welcome_screen", this);
65 if (!foundtheme)
66 return false;
67
68 bool err = false;
69 UIUtilE::Assign(this, m_statusText, "status_text", &err);
70 UIUtilE::Assign(this, m_recordingText, "recording_text", &err);
71 UIUtilE::Assign(this, m_scheduledText, "scheduled_text", &err);
72 UIUtilE::Assign(this, m_warningText, "conflicts_text", &err);
73 UIUtilE::Assign(this, m_startFrontendButton, "startfrontend_button", &err);
74
75 if (err)
76 {
77 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'welcome_screen'");
78 return false;
79 }
80
82
83 m_startFrontendButton->SetText(tr("Start Frontend"));
86
88
90
93
94 return true;
95}
96
98{
99 QString startFECmd = gCoreContext->GetSetting("MythWelcomeStartFECmd",
100 m_appBinDir + "mythfrontend");
101
102 // Ensure we use the same platform for mythfrontend
103 QStringList args;
104 if (!startFECmd.contains("platform"))
105 args << QString("--platform %1").arg(QGuiApplication::platformName());
107 updateAll();
108 m_frontendIsRunning = false;
109}
110
112{
114 return;
115
116 m_frontendIsRunning = true;
117
118 // this makes sure the button appears to click properly
119 QTimer::singleShot(500ms, this, &WelcomeDialog::startFrontend);
120}
121
123{
124 // mythshutdown --startup returns 0 for automatic startup
125 // 1 for manual startup
126 QString command = m_appBinDir + "mythshutdown --startup";
127 command += logPropagateArgs;
128 uint state = myth_system(command, kMSDontBlockInputDevs);
129
130 LOG(VB_GENERAL, LOG_NOTICE,
131 QString("mythshutdown --startup returned: %1").arg(state));
132
133 bool bAutoStartFrontend = gCoreContext->GetBoolSetting("AutoStartFrontend", true);
134
135 if (state == 1 && bAutoStartFrontend)
137
138 // update status now
139 updateAll();
140}
141
143{
144 if (e->type() == MythEvent::kMythEventMessage)
145 {
146 auto *me = dynamic_cast<MythEvent *>(e);
147 if (me == nullptr)
148 return;
149
150 if (me->Message().startsWith("RECORDING_LIST_CHANGE") ||
151 me->Message() == "UPDATE_PROG_INFO")
152 {
153 LOG(VB_GENERAL, LOG_NOTICE,
154 "MythWelcome received a recording list change event");
155
156 QMutexLocker lock(&m_recListUpdateMuxtex);
157
159 {
160 LOG(VB_GENERAL, LOG_NOTICE,
161 " [deferred to pending handler]");
162 }
163 else
164 {
165 // we can't query the backend from inside a customEvent
166 QTimer::singleShot(500ms, this, &WelcomeDialog::updateRecordingList);
168 }
169 }
170 else if (me->Message().startsWith("SCHEDULE_CHANGE"))
171 {
172 LOG(VB_GENERAL, LOG_NOTICE,
173 "MythWelcome received a SCHEDULE_CHANGE event");
174
175 QMutexLocker lock(&m_schedUpdateMuxtex);
176
177 if (pendingSchedUpdate())
178 {
179 LOG(VB_GENERAL, LOG_NOTICE,
180 " [deferred to pending handler]");
181 }
182 else
183 {
184 QTimer::singleShot(500ms, this, &WelcomeDialog::updateScheduledList);
186 }
187 }
188 else if (me->Message().startsWith("SHUTDOWN_COUNTDOWN"))
189 {
190#if 0
191 LOG(VB_GENERAL, LOG_NOTICE,
192 "MythWelcome received a SHUTDOWN_COUNTDOWN event");
193#endif
194 QString secs = me->Message().mid(19);
195 m_secondsToShutdown = secs.toInt();
197 updateScreen();
198 }
199 else if (me->Message().startsWith("SHUTDOWN_NOW"))
200 {
201 LOG(VB_GENERAL, LOG_NOTICE,
202 "MythWelcome received a SHUTDOWN_NOW event");
204 {
205 // does the user want to shutdown this frontend only machine
206 // when the BE shuts down?
207 if (gCoreContext->GetNumSetting("ShutdownWithMasterBE", 0) == 1)
208 {
209 LOG(VB_GENERAL, LOG_NOTICE,
210 "MythWelcome is shutting this computer down now");
211 QString poweroff_cmd = gCoreContext->GetSetting("MythShutdownPowerOff", "");
212 if (!poweroff_cmd.isEmpty())
213 myth_system(poweroff_cmd, kMSDontBlockInputDevs);
214 }
215 }
216 }
217 }
218}
219
221{
223 auto *ssd = new StandardSettingDialog(mainStack, "settings", screen);
224 if (ssd->Create())
225 mainStack->AddScreen(ssd);
226 else
227 delete ssd;
228}
229
230bool WelcomeDialog::keyPressEvent(QKeyEvent *event)
231{
232 if (GetFocusWidget()->keyPressEvent(event))
233 return true;
234
235 QStringList actions;
236 bool handled = GetMythMainWindow()->TranslateKeyPress("Welcome", event, actions);
237
238 for (int i = 0; i < actions.size() && !handled; i++)
239 {
240 const QString& action = actions[i];
241 handled = true;
242
243 if (action == "ESCAPE")
244 {
245 return true; // eat escape key
246 }
247 if (action == "MENU")
248 {
249 ShowMenu();
250 }
251 else if (action == "NEXTVIEW")
252 {
253 Close();
254 }
255 else if (action == "INFO")
256 {
258 }
259 else if (action == "SHOWSETTINGS")
260 {
262 }
263 else if (action == "0")
264 {
265 QString mythshutdown_status =
266 m_appBinDir + "mythshutdown --status 0";
267 QString mythshutdown_unlock =
268 m_appBinDir + "mythshutdown --unlock";
269 QString mythshutdown_lock =
270 m_appBinDir + "mythshutdown --lock";
271
272 uint statusCode =
273 myth_system(mythshutdown_status + logPropagateArgs, kMSDontBlockInputDevs);
274
275 // is shutdown locked by a user
276 if (!(statusCode & 0xFF00) && statusCode & 16)
277 {
278 myth_system(mythshutdown_unlock + logPropagateArgs, kMSDontBlockInputDevs);
279 }
280 else
281 {
283 }
284
286 updateScreen();
287 }
288 else if (action == "STARTXTERM")
289 {
290 QString cmd = gCoreContext->GetSetting("MythShutdownXTermCmd", "");
291 if (!cmd.isEmpty())
293 }
294 else if (action == "STARTSETUP")
295 {
296 QString mythtv_setup = m_appBinDir + "mythtv-setup";
297 myth_system(mythtv_setup + logPropagateArgs);
298 }
299 else
300 {
301 handled = false;
302 }
303 }
304
305 if (!handled && MythScreenType::keyPressEvent(event))
306 handled = true;
307
308 return handled;
309}
310
312{
313 Close();
314}
315
317{
319
321 m_updateStatusTimer->disconnect();
322
324 m_updateScreenTimer->disconnect();
325}
326
328{
330
332}
333
335{
336 QString status;
337
339 {
340 m_recordingText->SetText(tr("Cannot connect to server!"));
341 m_scheduledText->SetText(tr("Cannot connect to server!"));
343 }
344 else
345 {
346 // update recording
347 if (m_isRecording && !m_tunerList.empty())
348 {
350
351 while (!tuner.isRecording)
352 {
353 if (m_screenTunerNo < m_tunerList.size() - 1)
355 else
356 m_screenTunerNo = 0;
358 }
359
360 status = tr("Tuner %1 is recording:").arg(tuner.id);
361 status += "\n";
362 status += tuner.channame;
363 status += "\n" + tuner.title;
364 if (!tuner.subtitle.isEmpty())
365 status += "\n("+tuner.subtitle+")";
366
367 status += "\n" +
368 tr("%1 to %2", "Time period, 'starttime to endtime'")
371 }
372 else
373 {
374 status = tr("There are no recordings currently taking place");
375 }
376
377 m_recordingText->SetText(status);
378
379 // update scheduled
380 if (!m_scheduledList.empty())
381 {
384
386
387 InfoMap infomap;
388 progInfo.ToMap(infomap);
389
390 //status = QString("%1 of %2\n").arg(m_screenScheduledNo + 1)
391 // .arg(m_scheduledList.size());
392 status = infomap["channame"] + "\n";
393 status += infomap["title"];
394 if (!infomap["subtitle"].isEmpty())
395 status += "\n(" + infomap["subtitle"] + ")";
396
397 status += "\n" + infomap["timedate"];
398
399 if (m_screenScheduledNo < m_scheduledList.size() - 1)
401 else
403 }
404 else
405 {
406 status = tr("There are no scheduled recordings");
407 }
408
409 m_scheduledText->SetText(status);
410 }
411
412 // update status message
413 if (m_statusList.empty())
414 {
415 status = tr("Please Wait...");
416 }
417 else
418 {
419 if ((int)m_statusListNo >= m_statusList.count())
420 m_statusListNo = 0;
421
423 if (m_statusList.count() > 1)
424 status += "...";
425 m_statusText->SetText(status);
426
427 if ((int)m_statusListNo < m_statusList.count() - 1)
429 else
430 m_statusListNo = 0;
431 }
432
433 m_updateScreenTimer->stop();
434 m_updateScreenTimer->setSingleShot(true);
436}
437
438// taken from housekeeper.cpp
440{
441 QString command;
442
443 QString mfpath = gCoreContext->GetSetting("MythFillDatabasePath",
444 "mythfilldatabase");
445 QString mfarg = gCoreContext->GetSetting("MythFillDatabaseArgs", "");
446
447 command = QString("%1 %2").arg(mfpath, mfarg);
448 command += logPropagateArgs;
449
450 command += "&";
451
452 LOG(VB_GENERAL, LOG_INFO, QString("Grabbing EPG data using command: %1\n")
453 .arg(command));
454
456}
457
459{
462}
463
465{
466 {
467 // clear pending flag early in case something happens while
468 // we're updating
469 QMutexLocker lock(&m_recListUpdateMuxtex);
471 }
472
473 m_tunerList.clear();
474 m_isRecording = false;
475 m_screenTunerNo = 0;
476
478 return false;
479
481
482 return true;
483}
484
486{
487 {
488 // clear pending flag early in case something happens while
489 // we're updating
490 QMutexLocker lock(&m_schedUpdateMuxtex);
492 }
493
494 m_scheduledList.clear();
496
498 {
500 return false;
501 }
502
505
506 updateStatus();
507 updateScreen();
508
509 return true;
510}
511
513{
514 m_statusList.clear();
515
516 QDateTime curtime = MythDate::current();
517
518 if (!m_isRecording && !m_nextRecordingStart.isNull() &&
519 std::chrono::seconds(curtime.secsTo(m_nextRecordingStart)) - m_preRollSeconds <
521 {
522 m_statusList.append(tr("MythTV is about to start recording."));
523 }
524
525 if (m_isRecording)
526 {
527 m_statusList.append(tr("MythTV is busy recording."));
528 }
529
530 QString mythshutdown_status = m_appBinDir + "mythshutdown --status 0";
531 uint statusCode = myth_system(mythshutdown_status + logPropagateArgs, kMSDontBlockInputDevs);
532
533 if (!(statusCode & 0xFF00))
534 {
535 if (statusCode & 1)
536 m_statusList.append(tr("MythTV is busy transcoding."));
537 if (statusCode & 2)
538 m_statusList.append(tr("MythTV is busy flagging commercials."));
539 if (statusCode & 4)
540 m_statusList.append(tr("MythTV is busy grabbing EPG data."));
541 if (statusCode & 16)
542 m_statusList.append(tr("MythTV is locked by a user."));
543 if (statusCode & 32)
544 m_statusList.append(tr("MythTV has running or pending jobs."));
545 if (statusCode & 64)
546 m_statusList.append(tr("MythTV is in a daily wakeup/shutdown period."));
547 if (statusCode & 128)
548 m_statusList.append(tr("MythTV is about to start a wakeup/shutdown period."));
549 }
550
551 if (m_statusList.empty())
552 {
554 {
555 m_statusList.append(tr("MythTV is idle and will shutdown in %n "
556 "second(s).", "", m_secondsToShutdown));
557 }
558 else
559 {
560 m_statusList.append(tr("MythTV is idle."));
561 }
562 }
563
565}
566
568{
569 m_updateStatusTimer->stop();
570
571 bool bRes = false;
572
574 {
575 bRes = true;
576 }
577 else
578 {
580 {
581 bRes = true;
582 updateAll();
583 }
584 else
585 {
586 updateScreen();
587 }
588 }
589
590 if (bRes)
592 else
593 m_updateStatusTimer->start(5s);
594
595 return bRes;
596}
597
599{
600 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
601
602 m_menuPopup = new MythDialogBox("Menu", popupStack, "actionmenu");
603
604 if (m_menuPopup->Create())
605 popupStack->AddScreen(m_menuPopup);
606
607 m_menuPopup->SetReturnEvent(this, "action");
608
609 QString mythshutdown_status = m_appBinDir + "mythshutdown --status 0";
610 uint statusCode = myth_system(mythshutdown_status + logPropagateArgs, kMSDontBlockInputDevs);
611
612 if (!(statusCode & 0xFF00) && statusCode & 16)
613 m_menuPopup->AddButton(tr("Unlock Shutdown"), &WelcomeDialog::unlockShutdown);
614 else
615 m_menuPopup->AddButton(tr("Lock Shutdown"), &WelcomeDialog::lockShutdown);
616
617 m_menuPopup->AddButton(tr("Run mythfilldatabase"), &WelcomeDialog::runEPGGrabber);
618 m_menuPopup->AddButton(tr("Shutdown Now"), &WelcomeDialog::shutdownNow);
620 m_menuPopup->AddButton(tr("Cancel"));
621}
622
624{
625 QString command = m_appBinDir + "mythshutdown --lock";
626 command += logPropagateArgs;
629 updateScreen();
630}
631
633{
634 QString command = m_appBinDir + "mythshutdown --unlock";
635 command += logPropagateArgs;
638 updateScreen();
639}
640
642{
644 std::this_thread::sleep_for(1s);
646 updateScreen();
647}
648
650{
651 // if this is a frontend only machine just shut down now
653 {
654 LOG(VB_GENERAL, LOG_INFO,
655 "MythWelcome is shutting this computer down now");
656 QString poweroff_cmd = gCoreContext->GetSetting("MythShutdownPowerOff", "");
657 if (!poweroff_cmd.isEmpty())
658 myth_system(poweroff_cmd, kMSDontBlockInputDevs);
659 return;
660 }
661
662 // don't shutdown if we are recording
663 if (m_isRecording)
664 {
665 ShowOkPopup(tr("Cannot shutdown because MythTV is currently recording"));
666 return;
667 }
668
669 QDateTime curtime = MythDate::current();
670
671 // don't shutdown if we are about to start recording
672 if (!m_nextRecordingStart.isNull() &&
673 std::chrono::seconds(curtime.secsTo(m_nextRecordingStart)) - m_preRollSeconds <
675 {
676 ShowOkPopup(tr("Cannot shutdown because MythTV is about to start recording"));
677 return;
678 }
679
680 // don't shutdown if we are about to start a wakeup/shutdown period
681 QString command = m_appBinDir + "mythshutdown --status 0";
682 command += logPropagateArgs;
683
684 uint statusCode = myth_system(command, kMSDontBlockInputDevs);
685 if (!(statusCode & 0xFF00) && statusCode & 128)
686 {
687 ShowOkPopup(tr("Cannot shutdown because MythTV is about to start "
688 "a wakeup/shutdown period."));
689 return;
690 }
691
692 // set the wakeup time for the next scheduled recording
693 if (!m_nextRecordingStart.isNull())
694 {
695 QDateTime restarttime = m_nextRecordingStart.addSecs((-1) * m_preRollSeconds.count());
696
697 int add = gCoreContext->GetNumSetting("StartupSecsBeforeRecording", 240);
698 if (add)
699 restarttime = restarttime.addSecs((-1LL) * add);
700
701 QString wakeup_timeformat = gCoreContext->GetSetting("WakeupTimeFormat",
702 "yyyy-MM-ddThh:mm");
703 QString setwakeup_cmd = gCoreContext->GetSetting("SetWakeuptimeCommand",
704 "echo \'Wakeuptime would "
705 "be $time if command "
706 "set.\'");
707
708 if (wakeup_timeformat == "time_t")
709 {
710 QString time_ts;
711 setwakeup_cmd.replace("$time",
712 time_ts.setNum(restarttime.toSecsSinceEpoch())
713 );
714 }
715 else
716 {
717 setwakeup_cmd.replace(
718 "$time", restarttime.toLocalTime().toString(wakeup_timeformat));
719 }
720
721 if (!setwakeup_cmd.isEmpty())
722 {
723 myth_system(setwakeup_cmd, kMSDontBlockInputDevs);
724 }
725 }
726
727 // run command to set wakeuptime in bios and shutdown the system
728 command = QString();
729
730#ifndef Q_OS_WINDOWS
731 command = "sudo ";
732#endif
733
734 command += m_appBinDir + "mythshutdown --shutdown" + logPropagateArgs;
735
737}
738
bool IsConnectedToMaster(void)
bool SafeConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
QString GetSetting(const QString &key, const QString &defaultval="")
bool IsFrontendOnly(void)
is there a frontend, but no backend, running on this host
T GetDurSetting(const QString &key, T defaultval=T::zero())
int GetNumSetting(const QString &key, int defaultval=0)
bool GetBoolSetting(const QString &key, bool defaultval=false)
Basic menu dialog, message and a list of options.
void AddButton(const QString &title)
void SetReturnEvent(QObject *retobject, const QString &resultid)
bool Create(void) override
This class is used as a container for messages.
Definition: mythevent.h:17
static const Type kMythEventMessage
Definition: mythevent.h:79
MythScreenStack * GetMainStack()
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
MythScreenStack * GetStack(const QString &Stackname)
void addListener(QObject *listener)
Add a listener to the observable.
void removeListener(QObject *listener)
Remove a listener to the observable.
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
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)
virtual void Close()
void SetText(const QString &msg)
void Clicked()
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:115
virtual void SetVisible(bool visible)
Holds information on recordings and videos.
Definition: programinfo.h:74
virtual void ToMap(InfoMap &progMap, bool showrerecord=false, uint star_range=10, uint date_format=0) const
Converts ProgramInfo into QString QHash containing each field in ProgramInfo converted into localized...
recording status stuff
Definition: tvremoteutil.h:17
bool isRecording
Definition: tvremoteutil.h:20
QDateTime endTime
Definition: tvremoteutil.h:25
QString subtitle
Definition: tvremoteutil.h:23
QString channame
Definition: tvremoteutil.h:21
QString title
Definition: tvremoteutil.h:22
QDateTime startTime
Definition: tvremoteutil.h:24
QTimer * m_updateScreenTimer
Definition: welcomedialog.h:68
QString m_appBinDir
Definition: welcomedialog.h:70
void setPendingSchedUpdate(bool newState)
Definition: welcomedialog.h:98
std::vector< TunerStatus > m_tunerList
Definition: welcomedialog.h:85
void lockShutdown(void)
bool checkConnectionToServer(void)
QDateTime m_nextRecordingStart
Definition: welcomedialog.h:75
void checkAutoStart(void)
void ShowMenu(void) override
bool updateRecordingList(void)
void customEvent(QEvent *e) override
bool pendingSchedUpdate() const
Definition: welcomedialog.h:97
static void ShowSettings(GroupSetting *screen)
MythUIText * m_recordingText
Definition: welcomedialog.h:59
uint m_screenScheduledNo
Definition: welcomedialog.h:80
std::chrono::seconds m_preRollSeconds
Definition: welcomedialog.h:76
QTimer * m_updateStatusTimer
Definition: welcomedialog.h:67
MythUIButton * m_startFrontendButton
Definition: welcomedialog.h:63
uint m_screenTunerNo
Definition: welcomedialog.h:79
std::chrono::seconds m_idleWaitForRecordingTime
Definition: welcomedialog.h:77
void startFrontendClick(void)
void setPendingRecListUpdate(bool newState)
Definition: welcomedialog.h:92
QMutex m_recListUpdateMuxtex
Definition: welcomedialog.h:88
std::chrono::seconds m_idleTimeoutSecs
Definition: welcomedialog.h:78
MythUIText * m_warningText
Definition: welcomedialog.h:61
void runEPGGrabber(void)
int m_secondsToShutdown
Definition: welcomedialog.h:74
MythUIText * m_statusText
Definition: welcomedialog.h:58
QMutex m_schedUpdateMuxtex
Definition: welcomedialog.h:94
void updateStatus(void)
bool Create(void) override
~WelcomeDialog() override
void updateAll(void)
QStringList m_statusList
Definition: welcomedialog.h:82
bool m_frontendIsRunning
Definition: welcomedialog.h:83
void shutdownNow(void)
std::vector< ProgramInfo > m_scheduledList
Definition: welcomedialog.h:86
WelcomeDialog(MythScreenStack *parent, const char *name)
void updateScreen(void)
static void runMythFillDatabase(void)
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
MythDialogBox * m_menuPopup
Definition: welcomedialog.h:65
MythUIText * m_scheduledText
Definition: welcomedialog.h:60
bool updateScheduledList(void)
void updateStatusMessage(void)
bool pendingRecListUpdate() const
Definition: welcomedialog.h:91
void startFrontend(void)
void unlockShutdown(void)
void closeDialog(void)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
unsigned int uint
Definition: compat.h:60
QString logPropagateArgs
Definition: logging.cpp:86
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
QString GetAppBinDir(void)
Definition: mythdirs.cpp:282
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
@ kMSDontBlockInputDevs
avoid blocking LIRC & Joystick Menu
Definition: mythsystem.h:36
@ kMSProcessEvents
process events while waiting
Definition: mythsystem.h:39
@ kMSDisableUDPListener
disable MythMessage UDP listener for the duration of application.
Definition: mythsystem.h:50
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
@ kTime
Default local time.
Definition: mythdate.h:22
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
bool GetNextRecordingList(QDateTime &nextRecordingStart, bool *hasConflicts, std::vector< ProgramInfo > *list)
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
bool RemoteGetRecordingStatus(std::vector< TunerStatus > *tunerList, bool list_inactive)
static constexpr std::chrono::milliseconds UPDATE_SCREEN_INTERVAL
static constexpr std::chrono::milliseconds UPDATE_STATUS_INTERVAL