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,0,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 status = tr("Please Wait...");
415 else
416 {
417 if ((int)m_statusListNo >= m_statusList.count())
418 m_statusListNo = 0;
419
421 if (m_statusList.count() > 1)
422 status += "...";
423 m_statusText->SetText(status);
424
425 if ((int)m_statusListNo < m_statusList.count() - 1)
427 else
428 m_statusListNo = 0;
429 }
430
431 m_updateScreenTimer->stop();
432 m_updateScreenTimer->setSingleShot(true);
434}
435
436// taken from housekeeper.cpp
438{
439 QString command;
440
441 QString mfpath = gCoreContext->GetSetting("MythFillDatabasePath",
442 "mythfilldatabase");
443 QString mfarg = gCoreContext->GetSetting("MythFillDatabaseArgs", "");
444
445 command = QString("%1 %2").arg(mfpath, mfarg);
446 command += logPropagateArgs;
447
448 command += "&";
449
450 LOG(VB_GENERAL, LOG_INFO, QString("Grabbing EPG data using command: %1\n")
451 .arg(command));
452
454}
455
457{
460}
461
463{
464 {
465 // clear pending flag early in case something happens while
466 // we're updating
467 QMutexLocker lock(&m_recListUpdateMuxtex);
469 }
470
471 m_tunerList.clear();
472 m_isRecording = false;
473 m_screenTunerNo = 0;
474
476 return false;
477
479
480 return true;
481}
482
484{
485 {
486 // clear pending flag early in case something happens while
487 // we're updating
488 QMutexLocker lock(&m_schedUpdateMuxtex);
490 }
491
492 m_scheduledList.clear();
494
496 {
498 return false;
499 }
500
503
504 updateStatus();
505 updateScreen();
506
507 return true;
508}
509
511{
512 m_statusList.clear();
513
514 QDateTime curtime = MythDate::current();
515
516 if (!m_isRecording && !m_nextRecordingStart.isNull() &&
517 std::chrono::seconds(curtime.secsTo(m_nextRecordingStart)) - m_preRollSeconds <
519 {
520 m_statusList.append(tr("MythTV is about to start recording."));
521 }
522
523 if (m_isRecording)
524 {
525 m_statusList.append(tr("MythTV is busy recording."));
526 }
527
528 QString mythshutdown_status = m_appBinDir + "mythshutdown --status 0";
529 uint statusCode = myth_system(mythshutdown_status + logPropagateArgs, kMSDontBlockInputDevs);
530
531 if (!(statusCode & 0xFF00))
532 {
533 if (statusCode & 1)
534 m_statusList.append(tr("MythTV is busy transcoding."));
535 if (statusCode & 2)
536 m_statusList.append(tr("MythTV is busy flagging commercials."));
537 if (statusCode & 4)
538 m_statusList.append(tr("MythTV is busy grabbing EPG data."));
539 if (statusCode & 16)
540 m_statusList.append(tr("MythTV is locked by a user."));
541 if (statusCode & 32)
542 m_statusList.append(tr("MythTV has running or pending jobs."));
543 if (statusCode & 64)
544 m_statusList.append(tr("MythTV is in a daily wakeup/shutdown period."));
545 if (statusCode & 128)
546 m_statusList.append(tr("MythTV is about to start a wakeup/shutdown period."));
547 }
548
549 if (m_statusList.empty())
550 {
552 {
553 m_statusList.append(tr("MythTV is idle and will shutdown in %n "
554 "second(s).", "", m_secondsToShutdown));
555 }
556 else
557 {
558 m_statusList.append(tr("MythTV is idle."));
559 }
560 }
561
563}
564
566{
567 m_updateStatusTimer->stop();
568
569 bool bRes = false;
570
572 bRes = true;
573 else
574 {
576 {
577 bRes = true;
578 updateAll();
579 }
580 else
581 {
582 updateScreen();
583 }
584 }
585
586 if (bRes)
588 else
589 m_updateStatusTimer->start(5s);
590
591 return bRes;
592}
593
595{
596 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
597
598 m_menuPopup = new MythDialogBox("Menu", popupStack, "actionmenu");
599
600 if (m_menuPopup->Create())
601 popupStack->AddScreen(m_menuPopup);
602
603 m_menuPopup->SetReturnEvent(this, "action");
604
605 QString mythshutdown_status = m_appBinDir + "mythshutdown --status 0";
606 uint statusCode = myth_system(mythshutdown_status + logPropagateArgs, kMSDontBlockInputDevs);
607
608 if (!(statusCode & 0xFF00) && statusCode & 16)
609 m_menuPopup->AddButton(tr("Unlock Shutdown"), &WelcomeDialog::unlockShutdown);
610 else
611 m_menuPopup->AddButton(tr("Lock Shutdown"), &WelcomeDialog::lockShutdown);
612
613 m_menuPopup->AddButton(tr("Run mythfilldatabase"), &WelcomeDialog::runEPGGrabber);
614 m_menuPopup->AddButton(tr("Shutdown Now"), &WelcomeDialog::shutdownNow);
616 m_menuPopup->AddButton(tr("Cancel"));
617}
618
620{
621 QString command = m_appBinDir + "mythshutdown --lock";
622 command += logPropagateArgs;
625 updateScreen();
626}
627
629{
630 QString command = m_appBinDir + "mythshutdown --unlock";
631 command += logPropagateArgs;
634 updateScreen();
635}
636
638{
640 std::this_thread::sleep_for(1s);
642 updateScreen();
643}
644
646{
647 // if this is a frontend only machine just shut down now
649 {
650 LOG(VB_GENERAL, LOG_INFO,
651 "MythWelcome is shutting this computer down now");
652 QString poweroff_cmd = gCoreContext->GetSetting("MythShutdownPowerOff", "");
653 if (!poweroff_cmd.isEmpty())
654 myth_system(poweroff_cmd, kMSDontBlockInputDevs);
655 return;
656 }
657
658 // don't shutdown if we are recording
659 if (m_isRecording)
660 {
661 ShowOkPopup(tr("Cannot shutdown because MythTV is currently recording"));
662 return;
663 }
664
665 QDateTime curtime = MythDate::current();
666
667 // don't shutdown if we are about to start recording
668 if (!m_nextRecordingStart.isNull() &&
669 std::chrono::seconds(curtime.secsTo(m_nextRecordingStart)) - m_preRollSeconds <
671 {
672 ShowOkPopup(tr("Cannot shutdown because MythTV is about to start recording"));
673 return;
674 }
675
676 // don't shutdown if we are about to start a wakeup/shutdown period
677 QString command = m_appBinDir + "mythshutdown --status 0";
678 command += logPropagateArgs;
679
680 uint statusCode = myth_system(command, kMSDontBlockInputDevs);
681 if (!(statusCode & 0xFF00) && statusCode & 128)
682 {
683 ShowOkPopup(tr("Cannot shutdown because MythTV is about to start "
684 "a wakeup/shutdown period."));
685 return;
686 }
687
688 // set the wakeup time for the next scheduled recording
689 if (!m_nextRecordingStart.isNull())
690 {
691 QDateTime restarttime = m_nextRecordingStart.addSecs((-1) * m_preRollSeconds.count());
692
693 int add = gCoreContext->GetNumSetting("StartupSecsBeforeRecording", 240);
694 if (add)
695 restarttime = restarttime.addSecs((-1LL) * add);
696
697 QString wakeup_timeformat = gCoreContext->GetSetting("WakeupTimeFormat",
698 "yyyy-MM-ddThh:mm");
699 QString setwakeup_cmd = gCoreContext->GetSetting("SetWakeuptimeCommand",
700 "echo \'Wakeuptime would "
701 "be $time if command "
702 "set.\'");
703
704 if (wakeup_timeformat == "time_t")
705 {
706 QString time_ts;
707 setwakeup_cmd.replace("$time",
708 time_ts.setNum(restarttime.toSecsSinceEpoch())
709 );
710 }
711 else
712 {
713 setwakeup_cmd.replace(
714 "$time", restarttime.toLocalTime().toString(wakeup_timeformat));
715 }
716
717 if (!setwakeup_cmd.isEmpty())
718 {
719 myth_system(setwakeup_cmd, kMSDontBlockInputDevs);
720 }
721 }
722
723 // run command to set wakeuptime in bios and shutdown the system
724 command = QString();
725
726#ifndef Q_OS_WINDOWS
727 command = "sudo ";
728#endif
729
730 command += m_appBinDir + "mythshutdown --shutdown" + logPropagateArgs;
731
733}
734
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
int GetNumSetting(const QString &key, int defaultval=0)
std::enable_if_t< std::chrono::__is_duration< T >::value, T > GetDurSetting(const QString &key, T defaultval=T::zero())
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:66
QString m_appBinDir
Definition: welcomedialog.h:68
void setPendingSchedUpdate(bool newState)
Definition: welcomedialog.h:96
std::vector< TunerStatus > m_tunerList
Definition: welcomedialog.h:83
void lockShutdown(void)
bool checkConnectionToServer(void)
QDateTime m_nextRecordingStart
Definition: welcomedialog.h:73
void checkAutoStart(void)
void ShowMenu(void) override
bool updateRecordingList(void)
void customEvent(QEvent *e) override
bool pendingSchedUpdate() const
Definition: welcomedialog.h:95
static void ShowSettings(GroupSetting *screen)
MythUIText * m_recordingText
Definition: welcomedialog.h:57
uint m_screenScheduledNo
Definition: welcomedialog.h:78
std::chrono::seconds m_preRollSeconds
Definition: welcomedialog.h:74
QTimer * m_updateStatusTimer
Definition: welcomedialog.h:65
MythUIButton * m_startFrontendButton
Definition: welcomedialog.h:61
uint m_screenTunerNo
Definition: welcomedialog.h:77
std::chrono::seconds m_idleWaitForRecordingTime
Definition: welcomedialog.h:75
void startFrontendClick(void)
void setPendingRecListUpdate(bool newState)
Definition: welcomedialog.h:90
QMutex m_recListUpdateMuxtex
Definition: welcomedialog.h:86
std::chrono::seconds m_idleTimeoutSecs
Definition: welcomedialog.h:76
MythUIText * m_warningText
Definition: welcomedialog.h:59
void runEPGGrabber(void)
int m_secondsToShutdown
Definition: welcomedialog.h:72
MythUIText * m_statusText
Definition: welcomedialog.h:56
QMutex m_schedUpdateMuxtex
Definition: welcomedialog.h:92
void updateStatus(void)
bool Create(void) override
~WelcomeDialog() override
void updateAll(void)
QStringList m_statusList
Definition: welcomedialog.h:80
bool m_frontendIsRunning
Definition: welcomedialog.h:81
void shutdownNow(void)
std::vector< ProgramInfo > m_scheduledList
Definition: welcomedialog.h:84
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:63
MythUIText * m_scheduledText
Definition: welcomedialog.h:58
bool updateScheduledList(void)
void updateStatusMessage(void)
bool pendingRecListUpdate() const
Definition: welcomedialog.h:89
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