rendered paste bodyIndex: programs/mythbackend/scheduler.h
===================================================================
--- programs/mythbackend/scheduler.h (revision 26756)
+++ programs/mythbackend/scheduler.h (working copy)
@@ -148,6 +148,25 @@
const RecList &reclist);
void FillDirectoryInfoCache(bool force = false);
+ int CalcTimeToNextHandleRecordingEvent(
+ const QDateTime &curtime,
+ RecConstIter startIter, const RecList &reclist,
+ int prerollseconds, int max_sleep /*ms*/);
+ bool HandleReschedule(void);
+ bool HandleRunSchedulerStartup(
+ int prerollseconds, int idleWaitForRecordingTime);
+ void HandleWakeSlave(RecordingInfo &ri, int prerollseconds);
+ bool HandleRecording(
+ RecordingInfo &ri, bool &statuschanged, int prerollseconds);
+ void HandleTuning(
+ RecordingInfo &ri, bool &statuschanged);
+ void HandleRecordingStatusChange(
+ RecordingInfo &ri, RecStatusTypes recStatus, const QString &details);
+ void HandleIdleShutdown(
+ bool &blockShutdown, QDateTime &idleSince, int prerollseconds,
+ int idleTimeoutSecs, int idleWaitForRecordingTime);
+
+
MythDeque<int> reschedQueue;
QMutex reschedLock;
QMutex recordmatchLock;
Index: programs/mythbackend/scheduler.cpp
===================================================================
--- programs/mythbackend/scheduler.cpp (revision 26756)
+++ programs/mythbackend/scheduler.cpp (working copy)
@@ -17,6 +17,7 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <cmath>
#include <QStringList>
#include <QDateTime>
@@ -214,6 +215,7 @@
static inline bool Recording(const RecordingInfo *p)
{
return (p->GetRecordingStatus() == rsRecording ||
+ p->GetRecordingStatus() == rsTuning ||
p->GetRecordingStatus() == rsWillRecord);
}
@@ -289,8 +291,10 @@
static bool comp_priority(RecordingInfo *a, RecordingInfo *b)
{
- int arec = (a->GetRecordingStatus() != rsRecording);
- int brec = (b->GetRecordingStatus() != rsRecording);
+ int arec = (a->GetRecordingStatus() != rsRecording &&
+ a->GetRecordingStatus() != rsTuning);
+ int brec = (b->GetRecordingStatus() != rsRecording &&
+ b->GetRecordingStatus() != rsTuning);
if (arec != brec)
return arec < brec;
@@ -644,14 +648,14 @@
if (sp->GetCardID() == rp->GetCardID())
{
found = true;
- rp->SetRecordingStatus(rsRecording);
+ rp->SetRecordingStatus(sp->GetRecordingStatus());
reclist_changed = true;
rp->AddHistory(false);
- VERBOSE(VB_IMPORTANT, QString("setting %1/%2/\"%3\" as "
- "recording")
+ VERBOSE(VB_IMPORTANT, QString("setting %1/%2/\"%3\" as %4")
.arg(sp->GetCardID())
.arg(sp->GetChannelSchedulingID())
- .arg(sp->GetTitle()));
+ .arg(sp->GetTitle())
+ .arg(toUIState(sp->GetRecordingStatus())));
}
else
{
@@ -664,7 +668,8 @@
}
}
else if (sp->GetCardID() == rp->GetCardID() &&
- rp->GetRecordingStatus() == rsRecording)
+ (rp->GetRecordingStatus() == rsRecording ||
+ rp->GetRecordingStatus() == rsTuning))
{
rp->SetRecordingStatus(rsAborted);
reclist_changed = true;
@@ -699,7 +704,8 @@
RecordingInfo *rp = *ri;
if (rp->GetCardID() == cardid &&
- rp->GetRecordingStatus() == rsRecording)
+ (rp->GetRecordingStatus() == rsRecording ||
+ rp->GetRecordingStatus() == rsTuning))
{
rp->SetRecordingStatus(rsAborted);
reclist_changed = true;
@@ -720,7 +726,8 @@
for (; i != reclist.end(); ++i)
{
RecordingInfo *p = *i;
- if (p->GetRecordingStatus() == rsRecording)
+ if (p->GetRecordingStatus() == rsRecording ||
+ p->GetRecordingStatus() == rsTuning)
worklist.push_back(new RecordingInfo(*p));
}
}
@@ -806,6 +813,7 @@
{
RecordingInfo *p = *i;
if (p->GetRecordingStatus() == rsRecording ||
+ p->GetRecordingStatus() == rsTuning ||
p->GetRecordingStatus() == rsWillRecord ||
p->GetRecordingStatus() == rsUnknown)
{
@@ -1024,7 +1032,8 @@
{
PrintRec(p, " >");
- if (p->GetRecordingStatus() == rsRecording)
+ if (p->GetRecordingStatus() == rsRecording ||
+ p->GetRecordingStatus() == rsTuning)
return false;
RecList *showinglist = &titlelistmap[p->GetTitle()];
@@ -1171,7 +1180,8 @@
while (i != worklist.end())
{
RecordingInfo *p = *i;
- if (p->GetRecordingStatus() == rsRecording)
+ if (p->GetRecordingStatus() == rsRecording ||
+ p->GetRecordingStatus() == rsTuning)
MarkOtherShowings(p);
else if (p->GetRecordingStatus() == rsUnknown)
{
@@ -1304,6 +1314,7 @@
// Delete anything that has already passed since we can't
// change history, can we?
if (p->GetRecordingStatus() != rsRecording &&
+ p->GetRecordingStatus() != rsTuning &&
p->GetScheduledEndTime() < schedTime &&
p->GetRecordingEndTime() < schedTime)
{
@@ -1478,7 +1489,8 @@
RecConstIter it = reclist.begin();
for (; it != reclist.end(); ++it)
{
- if (rsRecording == (*it)->GetRecordingStatus())
+ if (rsRecording == (*it)->GetRecordingStatus() ||
+ rsTuning == (*it)->GetRecordingStatus())
recMap[(*it)->MakeUniqueKey()] = new ProgramInfo(**it);
}
@@ -1493,8 +1505,9 @@
{
if (pginfo.IsSameRecording(**it))
{
- return (rsRecording == (**it).GetRecordingStatus()) ?
- rsRecording : pginfo.GetRecordingStatus();
+ return (rsRecording == (**it).GetRecordingStatus() ||
+ rsTuning == (**it).GetRecordingStatus()) ?
+ (**it).GetRecordingStatus() : pginfo.GetRecordingStatus();
}
}
@@ -1630,41 +1643,14 @@
void Scheduler::RunScheduler(void)
{
- int prerollseconds = 0;
- int wakeThreshold = gCoreContext->GetNumSetting("WakeUpThreshold", 300);
- int secsleft = 0;
- EncoderLink *nexttv = NULL;
-
- RecordingInfo *nextRecording = NULL;
- QDateTime nextrectime;
- QString schedid;
-
- QDateTime curtime;
- QDateTime lastupdate = QDateTime::currentDateTime().addDays(-1);
- QDateTime lastSleepCheck = QDateTime::currentDateTime().addDays(-1);
-
- RecIter startIter = reclist.begin();
-
- bool blockShutdown = gCoreContext->GetNumSetting("blockSDWUwithoutClient", 1);
- QDateTime idleSince = QDateTime();
- int idleTimeoutSecs = 0;
- int idleWaitForRecordingTime = 0;
- bool firstRun = true;
-
- QString sysEventKey;
- int sysEventSecs[5] = { 120, 90, 60, 30, 0 };
- QList<QString>sysEvents[4];
-
- struct timeval fillstart, fillend;
- float matchTime, placeTime;
-
// Mark anything that was recording as aborted. We'll fix it up.
// if possible, after the slaves connect and we start scheduling.
MSqlQuery query(dbConn);
query.prepare("UPDATE oldrecorded SET recstatus = :RSABORTED "
- " WHERE recstatus = :RSRECORDING");
+ " WHERE recstatus = :RSRECORDING OR recstatus = :RSTUNING");
query.bindValue(":RSABORTED", rsAborted);
query.bindValue(":RSRECORDING", rsRecording);
+ query.bindValue(":RSTUNING", rsTuning);
if (!query.exec())
MythDB::DBError("UpdateAborted", query);
@@ -1673,603 +1659,807 @@
Reschedule(-1);
- while (1)
+ int prerollseconds = 0;
+ int wakeThreshold = 300;
+ int idleTimeoutSecs = 0;
+ int idleWaitForRecordingTime = 15; // in minutes
+ bool blockShutdown =
+ gCoreContext->GetNumSetting("blockSDWUwithoutClient", 1);
+ bool firstRun = true;
+ QDateTime lastSleepCheck = QDateTime::currentDateTime().addDays(-1);
+ RecIter startIter = reclist.begin();
+ QDateTime idleSince = QDateTime();
+ int maxSleep = 60000; // maximum sleep time in milliseconds
+ int schedRunTime = 30; // max scheduler run time in seconds
+
+ while (true)
{
- curtime = QDateTime::currentDateTime();
+ QDateTime curtime = QDateTime::currentDateTime();
bool statuschanged = false;
+ int secs_to_next = (startIter != reclist.end()) ?
+ curtime.secsTo((*startIter)->GetRecordingStartTime()) : 60*60;
- if ((startIter != reclist.end() &&
- curtime.secsTo((*startIter)->GetRecordingStartTime()) < 30))
- sleep(1);
+ // If we're about to start a recording don't do any reschedules...
+ // instead sleep for a bit
+ if (secs_to_next < (schedRunTime + 2))
+ {
+ int msecs = CalcTimeToNextHandleRecordingEvent(
+ curtime, startIter, reclist, prerollseconds, maxSleep);
+ if (msecs > 200)
+ (void) ::usleep(msecs * 1000);
+ }
else
{
+ int sched_sleep = (secs_to_next - schedRunTime - 1) * 1000;
+ sched_sleep = min(sched_sleep, maxSleep);
reschedLock.lock();
if (reschedQueue.empty())
- reschedWait.wait(&reschedLock, 1000);
+ reschedWait.wait(&reschedLock, sched_sleep);
bool queue_empty = reschedQueue.empty();
reschedLock.unlock();
- if (!queue_empty)
+ QTime t; t.start();
+ if (!queue_empty && HandleReschedule())
{
- // We might have been inactive for a long time, so make
- // sure our DB connection is fresh before continuing.
- dbConn = MSqlQuery::SchedCon();
+ statuschanged = true;
+ startIter = reclist.begin();
- gettimeofday(&fillstart, NULL);
- QString msg;
+ // The master backend is a long lived program, so
+ // we reload some key settings on each reschedule.
+ prerollseconds =
+ gCoreContext->GetNumSetting("RecordPreRoll", 0);
+ wakeThreshold =
+ gCoreContext->GetNumSetting("WakeUpThreshold", 300);
+ idleTimeoutSecs =
+ gCoreContext->GetNumSetting("idleTimeoutSecs", 0);
+ idleWaitForRecordingTime =
+ gCoreContext->GetNumSetting("idleWaitForRecordingTime", 15);
+ }
+ int e = t.elapsed();
+ if (e > 0)
+ {
+ schedRunTime = (firstRun) ? 0 : schedRunTime;
+ schedRunTime =
+ max((int) ceil((e + 999 / 1000) * 1.5f), schedRunTime);
+ VERBOSE(VB_IMPORTANT, QString("schedRunTime: %1 seconds")
+ .arg(schedRunTime));
+ }
- reschedLock.lock();
- while (!reschedQueue.empty())
- {
- int recordid = reschedQueue.dequeue();
- reschedLock.unlock();
+ if (firstRun)
+ {
+ blockShutdown &= HandleRunSchedulerStartup(
+ prerollseconds, idleWaitForRecordingTime);
+ firstRun = false;
+ }
- VERBOSE(VB_GENERAL,
- QString("Reschedule requested for id %1.")
- .arg(recordid));
+ // Unless a recording is about to start, check for slaves
+ // that can be put to sleep if it has been at least five
+ // minutes since we last put slaves to sleep.
+ curtime = QDateTime::currentDateTime();
+ secs_to_next = (startIter != reclist.end()) ?
+ curtime.secsTo((*startIter)->GetRecordingStartTime()) : 60*60;
+ if ((secs_to_next > schedRunTime * 1.5f) &&
+ (lastSleepCheck.secsTo(curtime) > 300))
+ {
+ PutInactiveSlavesToSleep();
+ lastSleepCheck = QDateTime::currentDateTime();
+ }
+ }
- if (recordid != 0)
- {
- if (recordid == -1)
- {
- reschedLock.lock();
- reschedQueue.clear();
- reschedLock.unlock();
- }
+ // Skip past recordings that are already history
+ // (i.e. AddHistory() has been called setting oldrecstatus)
+ for ( ; startIter != reclist.end(); ++startIter)
+ {
+ if ((*startIter)->GetRecordingStatus() !=
+ (*startIter)->oldrecstatus)
+ {
+ break;
+ }
+ }
- QMutexLocker locker(&recordmatchLock);
- UpdateMatches(recordid);
- }
+ // Start any recordings that are due to be started
+ // & call RecordPending for recordings due to start in 30 seconds
+ // & handle rsTuning updates
+ bool done = false;
+ for (RecIter it = startIter; it != reclist.end() && !done; ++it)
+ done = HandleRecording(**it, statuschanged, prerollseconds);
- reschedLock.lock();
- }
- reschedLock.unlock();
+ /// Wake any slave backends that need waking
+ curtime = QDateTime::currentDateTime();
+ for (RecIter it = startIter; it != reclist.end() && !done; ++it)
+ {
+ int secsleft = curtime.secsTo((*it)->GetRecordingStartTime());
+ if ((secsleft - prerollseconds) <= wakeThreshold)
+ HandleWakeSlave(**it, prerollseconds);
+ else
+ break;
+ }
- gettimeofday(&fillend, NULL);
+ if (statuschanged)
+ {
+ MythEvent me("SCHEDULE_CHANGE");
+ gCoreContext->dispatch(me);
+ idleSince = QDateTime();
+ }
- matchTime = ((fillend.tv_sec - fillstart.tv_sec ) * 1000000 +
- (fillend.tv_usec - fillstart.tv_usec)) / 1000000.0;
+ // if idletimeout is 0, the user disabled the auto-shutdown feature
+ if ((idleTimeoutSecs > 0) && (m_mainServer != NULL))
+ {
+ HandleIdleShutdown(blockShutdown, idleSince, prerollseconds,
+ idleTimeoutSecs, idleWaitForRecordingTime);
+ }
+ }
+}
- gettimeofday(&fillstart, NULL);
- bool worklistused = FillRecordList();
- gettimeofday(&fillend, NULL);
- if (worklistused)
- {
- UpdateNextRecord();
- PrintList();
- }
- else
- {
- VERBOSE(VB_GENERAL, "Reschedule interrupted, will retry");
- Reschedule(0);
- continue;
- }
+int Scheduler::CalcTimeToNextHandleRecordingEvent(
+ const QDateTime &curtime,
+ RecConstIter startIter, const RecList &reclist,
+ int prerollseconds, int max_sleep /*ms*/)
+{
+ if (startIter == reclist.end())
+ return max_sleep;
- placeTime = ((fillend.tv_sec - fillstart.tv_sec ) * 1000000 +
- (fillend.tv_usec - fillstart.tv_usec)) / 1000000.0;
+ int msecs = max_sleep;
+ for (RecConstIter i = startIter; i != reclist.end() && (msecs > 0); ++i)
+ {
+ // Check on recordings that we've told to start, but have
+ // not yet started every second or so.
+ if ((*i)->GetRecordingStatus() == rsTuning)
+ {
+ msecs = min(msecs, 1000);
+ continue;
+ }
- msg.sprintf("Scheduled %d items in "
- "%.1f = %.2f match + %.2f place",
- (int)reclist.size(),
- matchTime + placeTime, matchTime, placeTime);
+ // These recordings have already been handled..
+ if ((*i)->GetRecordingStatus() == (*i)->oldrecstatus)
+ continue;
- VERBOSE(VB_GENERAL, msg);
- gCoreContext->LogEntry("scheduler", LP_INFO,
- "Scheduled items", msg);
+ int secs_to_next = curtime.secsTo((*i)->GetRecordingStartTime());
- fsInfoCacheFillTime =
- QDateTime::currentDateTime().addSecs(-1000);
+ if (!recPendingList[(*i)->MakeUniqueSchedulerKey()])
+ secs_to_next -= 30;
- lastupdate = curtime;
- startIter = reclist.begin();
- statuschanged = true;
+ if (secs_to_next < 0)
+ {
+ msecs = 0;
+ break;
+ }
- // Determine if the user wants us to start recording early
- // and by how many seconds
- prerollseconds = gCoreContext->GetNumSetting("RecordPreRoll");
+ // This is what normally breaks us out of the loop...
+ if (secs_to_next > max_sleep)
+ {
+ msecs = min(msecs, max_sleep);
+ break;
+ }
- idleTimeoutSecs =
- gCoreContext->GetNumSetting("idleTimeoutSecs", 0);
- idleWaitForRecordingTime =
- gCoreContext->GetNumSetting("idleWaitForRecordingTime", 15);
+ if (secs_to_next > 31)
+ {
+ msecs = min(msecs, 30 * 1000);
+ continue;
+ }
- if (firstRun)
- {
- //the parameter given to the startup_cmd. "user" means a user
- // started the BE, 'auto' means it was started automatically
- QString startupParam = "user";
+ if ((secs_to_next-1) * 1000 > msecs)
+ continue;
- // find the first recording that WILL be recorded
- RecIter firstRunIter = reclist.begin();
- for ( ; firstRunIter != reclist.end(); ++firstRunIter)
- if ((*firstRunIter)->GetRecordingStatus() == rsWillRecord)
- break;
+ if (secs_to_next < 15)
+ {
+ QTime st = (*i)->GetRecordingStartTime().time();
+ int tmp = curtime.time().msecsTo(st);
+ tmp = (tmp < 0) ? tmp + 86400000 : tmp;
+ msecs = (tmp > 15*1000) ? 0 : min(msecs, tmp);
+ }
+ else
+ {
+ msecs = min(msecs, (secs_to_next-1) * 1000);
+ }
+ }
- // have we been started automatically?
- if (WasStartedAutomatically() ||
- ((firstRunIter != reclist.end()) &&
- ((curtime.secsTo((*firstRunIter)->GetRecordingStartTime()) - prerollseconds)
- < (idleWaitForRecordingTime * 60))))
- {
- VERBOSE(VB_IMPORTANT, "AUTO-Startup assumed");
- startupParam = "auto";
+ return min(msecs, max_sleep);
+}
- // Since we've started automatically, don't wait for
- // client to connect before allowing shutdown.
- blockShutdown = false;
- }
- else
- {
- VERBOSE(VB_IMPORTANT, "Seem to be woken up by USER");
- }
+bool Scheduler::HandleReschedule(void)
+{
+ // We might have been inactive for a long time, so make
+ // sure our DB connection is fresh before continuing.
+ dbConn = MSqlQuery::SchedCon();
- QString startupCommand =
- gCoreContext->GetSetting("startupCommand", "");
- if (!startupCommand.isEmpty())
- {
- startupCommand.replace("$status", startupParam);
- myth_system(startupCommand);
- }
- firstRun = false;
- }
+ struct timeval fillstart;
+ gettimeofday(&fillstart, NULL);
+ QString msg;
- PutInactiveSlavesToSleep();
- lastSleepCheck = QDateTime::currentDateTime();
+ reschedLock.lock();
+ while (!reschedQueue.empty())
+ {
+ int recordid = reschedQueue.dequeue();
+ reschedLock.unlock();
- SendMythSystemEvent("SCHEDULER_RAN");
+ VERBOSE(VB_GENERAL,
+ QString("Reschedule requested for id %1.")
+ .arg(recordid));
+
+ if (recordid != 0)
+ {
+ if (recordid == -1)
+ {
+ reschedLock.lock();
+ reschedQueue.clear();
+ reschedLock.unlock();
}
+
+ QMutexLocker locker(&recordmatchLock);
+ UpdateMatches(recordid);
}
- for ( ; startIter != reclist.end(); ++startIter)
- if ((*startIter)->GetRecordingStatus() !=
- (*startIter)->oldrecstatus)
- break;
+ reschedLock.lock();
+ }
+ reschedLock.unlock();
- curtime = QDateTime::currentDateTime();
+ struct timeval fillend;
+ gettimeofday(&fillend, NULL);
- // About every 5 minutes check for slaves that can be put to sleep
- if (lastSleepCheck.secsTo(curtime) > 300)
- {
- PutInactiveSlavesToSleep();
- lastSleepCheck = QDateTime::currentDateTime();
- }
+ float matchTime = ((fillend.tv_sec - fillstart.tv_sec ) * 1000000 +
+ (fillend.tv_usec - fillstart.tv_usec)) / 1000000.0;
- // Go through the list of recordings starting in the next few minutes
- // and wakeup any slaves that are asleep
- RecIter recIter = startIter;
- for ( ; schedulingEnabled && recIter != reclist.end(); ++recIter)
- {
- nextRecording = *recIter;
- nextrectime = nextRecording->GetRecordingStartTime();
- secsleft = curtime.secsTo(nextrectime);
+ gettimeofday(&fillstart, NULL);
+ bool worklistused = FillRecordList();
+ gettimeofday(&fillend, NULL);
+ if (worklistused)
+ {
+ UpdateNextRecord();
+ PrintList();
+ }
+ else
+ {
+ VERBOSE(VB_GENERAL, "Reschedule interrupted, will retry");
+ Reschedule(0);
+ return false;
+ }
- if ((secsleft - prerollseconds) > wakeThreshold)
- break;
+ float placeTime = ((fillend.tv_sec - fillstart.tv_sec ) * 1000000 +
+ (fillend.tv_usec - fillstart.tv_usec)) / 1000000.0;
- if (m_tvList->find(nextRecording->GetCardID()) == m_tvList->end())
- continue;
+ msg.sprintf("Scheduled %d items in "
+ "%.1f = %.2f match + %.2f place",
+ (int)reclist.size(),
+ matchTime + placeTime, matchTime, placeTime);
- sysEventKey = QString("%1:%2").arg(nextRecording->GetChanID())
- .arg(nextrectime.toString(Qt::ISODate));
- int i = 0;
- bool pendingEventSent = false;
- while (sysEventSecs[i] != 0)
- {
- if ((secsleft <= sysEventSecs[i]) &&
- (!sysEvents[i].contains(sysEventKey)))
- {
- if (!pendingEventSent)
- SendMythSystemRecEvent
- (QString("REC_PENDING SECS %1").arg(secsleft),
- nextRecording);
+ VERBOSE(VB_GENERAL, msg);
+ gCoreContext->LogEntry("scheduler", LP_INFO,
+ "Scheduled items", msg);
- sysEvents[i].append(sysEventKey);
- pendingEventSent = true;
- }
- i++;
- }
+ fsInfoCacheFillTime =
+ QDateTime::currentDateTime().addSecs(-1000);
- nexttv = (*m_tvList)[nextRecording->GetCardID()];
+ SendMythSystemEvent("SCHEDULER_RAN");
- if (nexttv->IsAsleep() && !nexttv->IsWaking())
- {
- VERBOSE(VB_SCHEDULE, QString("Slave Backend %1 is being "
- "awakened to record: %2")
- .arg(nexttv->GetHostName())
- .arg(nextRecording->GetTitle()));
+ return true;
+}
- if (!WakeUpSlave(nexttv->GetHostName()))
- {
- Reschedule(0);
- continue;
- }
- }
- else if ((nexttv->IsWaking()) &&
- ((secsleft - prerollseconds) < 210) &&
- (nexttv->GetSleepStatusTime().secsTo(curtime) < 300) &&
- (nexttv->GetLastWakeTime().secsTo(curtime) > 10))
+bool Scheduler::HandleRunSchedulerStartup(
+ int prerollseconds, int idleWaitForRecordingTime)
+{
+ bool blockShutdown = true;
+
+ // The parameter given to the startup_cmd. "user" means a user
+ // probably started the backend process, "auto" means it was
+ // started probably automatically.
+ QString startupParam = "user";
+
+ // find the first recording that WILL be recorded
+ RecIter firstRunIter = reclist.begin();
+ for ( ; firstRunIter != reclist.end(); ++firstRunIter)
+ {
+ if ((*firstRunIter)->GetRecordingStatus() == rsWillRecord)
+ break;
+ }
+
+ // have we been started automatically?
+ QDateTime curtime = QDateTime::currentDateTime();
+ if (WasStartedAutomatically() ||
+ ((firstRunIter != reclist.end()) &&
+ ((curtime.secsTo((*firstRunIter)->GetRecordingStartTime()) -
+ prerollseconds) < (idleWaitForRecordingTime * 60))))
+ {
+ VERBOSE(VB_GENERAL, LOC + "AUTO-Startup assumed");
+ startupParam = "auto";
+
+ // Since we've started automatically, don't wait for
+ // client to connect before allowing shutdown.
+ blockShutdown = false;
+ }
+ else
+ {
+ VERBOSE(VB_GENERAL, LOC + "Seem to be woken up by USER");
+ }
+
+ QString startupCommand = gCoreContext->GetSetting("startupCommand", "");
+ if (!startupCommand.isEmpty())
+ {
+ startupCommand.replace("$status", startupParam);
+ myth_system(startupCommand);
+ }
+
+ return blockShutdown;
+}
+
+// If a recording is about to start on a backend in a few minutes, wake it...
+void Scheduler::HandleWakeSlave(RecordingInfo &ri, int prerollseconds)
+{
+ static const int sysEventSecs[5] = { 120, 90, 60, 30, 0 };
+ QString sysEventKey;
+ QList<QString> sysEvents[4];
+
+ QDateTime curtime = QDateTime::currentDateTime();
+ QDateTime nextrectime = ri.GetRecordingStartTime();
+ int secsleft = curtime.secsTo(nextrectime);
+
+ QMap<int, EncoderLink*>::iterator tvit = m_tvList->find(ri.GetCardID());
+ if (tvit == m_tvList->end())
+ return;
+
+ sysEventKey = QString("%1:%2").arg(ri.GetChanID())
+ .arg(nextrectime.toString(Qt::ISODate));
+
+ int i = 0;
+ bool pendingEventSent = false;
+ while (sysEventSecs[i] != 0)
+ {
+ if ((secsleft <= sysEventSecs[i]) &&
+ (!sysEvents[i].contains(sysEventKey)))
+ {
+ if (!pendingEventSent)
{
- VERBOSE(VB_SCHEDULE, QString("Slave Backend %1 not "
- "available yet, trying to wake it up again.")
- .arg(nexttv->GetHostName()));
- if (!WakeUpSlave(nexttv->GetHostName(), false))
- {
- Reschedule(0);
- continue;
- }
+ SendMythSystemRecEvent(
+ QString("REC_PENDING SECS %1").arg(secsleft), &ri);
}
- else if ((nexttv->IsWaking()) &&
- ((secsleft - prerollseconds) < 150) &&
- (nexttv->GetSleepStatusTime().secsTo(curtime) < 300))
- {
- VERBOSE(VB_SCHEDULE,
- QString("WARNING: Slave Backend %1 has NOT come "
- "back from sleep yet in 150 seconds. Setting "
- "slave status to unknown and attempting "
- "to reschedule around its tuners.")
- .arg(nexttv->GetHostName()));
- QMap<int, EncoderLink *>::Iterator enciter =
- m_tvList->begin();
- for (; enciter != m_tvList->end(); ++enciter)
- {
- EncoderLink *enc = *enciter;
- if (enc->GetHostName() == nexttv->GetHostName())
- enc->SetSleepStatus(sStatus_Undefined);
- }
+ sysEvents[i].append(sysEventKey);
+ pendingEventSent = true;
+ }
+ i++;
+ }
- Reschedule(0);
- }
+ EncoderLink *nexttv = *tvit;
+
+ if (nexttv->IsAsleep() && !nexttv->IsWaking())
+ {
+ VERBOSE(VB_SCHEDULE, LOC +
+ QString("Slave Backend %1 is being awakened to record: %2")
+ .arg(nexttv->GetHostName()).arg(ri.GetTitle()));
+
+ if (!WakeUpSlave(nexttv->GetHostName()))
+ Reschedule(0);
+ }
+ else if ((nexttv->IsWaking()) &&
+ ((secsleft - prerollseconds) < 210) &&
+ (nexttv->GetSleepStatusTime().secsTo(curtime) < 300) &&
+ (nexttv->GetLastWakeTime().secsTo(curtime) > 10))
+ {
+ VERBOSE(VB_SCHEDULE, LOC +
+ QString("Slave Backend %1 not available yet, "
+ "trying to wake it up again.")
+ .arg(nexttv->GetHostName()));
+
+ if (!WakeUpSlave(nexttv->GetHostName(), false))
+ Reschedule(0);
+ }
+ else if ((nexttv->IsWaking()) &&
+ ((secsleft - prerollseconds) < 150) &&
+ (nexttv->GetSleepStatusTime().secsTo(curtime) < 300))
+ {
+ VERBOSE(VB_GENERAL, LOC_WARN +
+ QString("Slave Backend %1 has NOT come "
+ "back from sleep yet in 150 seconds. Setting "
+ "slave status to unknown and attempting "
+ "to reschedule around its tuners.")
+ .arg(nexttv->GetHostName()));
+
+ QMap<int, EncoderLink*>::iterator it = m_tvList->begin();
+ for (; it != m_tvList->end(); ++it)
+ {
+ if ((*it)->GetHostName() == nexttv->GetHostName())
+ (*it)->SetSleepStatus(sStatus_Undefined);
}
- for ( recIter = startIter ; recIter != reclist.end(); ++recIter)
+ Reschedule(0);
+ }
+}
+
+bool Scheduler::HandleRecording(
+ RecordingInfo &ri, bool &statuschanged, int prerollseconds)
+{
+ if (ri.GetRecordingStatus() == rsTuning)
+ {
+ HandleTuning(ri, statuschanged);
+ return false;
+ }
+
+ if (ri.GetRecordingStatus() != rsWillRecord)
+ {
+ if (ri.GetRecordingStatus() != ri.oldrecstatus &&
+ ri.GetRecordingStartTime() <= QDateTime::currentDateTime())
{
- QString msg, details;
- int fsID = -1;
+ ri.AddHistory(false);
+ }
+ return false;
+ }
- nextRecording = *recIter;
+ QDateTime nextrectime = ri.GetRecordingStartTime();
+ QDateTime curtime = QDateTime::currentDateTime();
+ int secsleft = curtime.secsTo(nextrectime);
+ QString schedid = ri.MakeUniqueSchedulerKey();
- if (nextRecording->GetRecordingStatus() != rsTuning)
- {
- if (nextRecording->GetRecordingStatus() != rsWillRecord)
- {
- if (nextRecording->GetRecordingStatus() !=
- nextRecording->oldrecstatus &&
- nextRecording->GetRecordingStartTime() <= curtime)
- nextRecording->AddHistory(false);
- continue;
- }
+ if (secsleft - prerollseconds < 60)
+ {
+ if (!recPendingList.contains(schedid))
+ {
+ recPendingList[schedid] = false;
+
+ livetvTime = (livetvTime < nextrectime) ?
+ nextrectime : livetvTime;
- nextrectime = nextRecording->GetRecordingStartTime();
- secsleft = curtime.secsTo(nextrectime);
- schedid = nextRecording->MakeUniqueSchedulerKey();
+ Reschedule(0);
+ }
+ }
- if (secsleft - prerollseconds < 60)
- {
- if (!recPendingList.contains(schedid))
- {
- recPendingList[schedid] = false;
+ if (secsleft - prerollseconds > 35)
+ return true;
- livetvTime = (livetvTime < nextrectime) ?
- nextrectime : livetvTime;
+ QMap<int, EncoderLink*>::iterator tvit = m_tvList->find(ri.GetCardID());
+ if (tvit == m_tvList->end())
+ {
+ QString msg = QString("Invalid cardid (%1) for %2")
+ .arg(ri.GetCardID()).arg(ri.GetTitle());
+ VERBOSE(VB_GENERAL, LOC + msg);
- Reschedule(0);
- }
- }
+ QMutexLocker lockit(reclist_lock);
+ ri.SetRecordingStatus(rsTunerBusy);
+ ri.AddHistory(true);
+ statuschanged = true;
+ return false;
+ }
- if (secsleft - prerollseconds > 35)
- break;
- }
+ EncoderLink *nexttv = *tvit;
- if (m_tvList->find(nextRecording->GetCardID()) == m_tvList->end())
- {
- msg = QString("invalid cardid (%1) for %2")
- .arg(nextRecording->GetCardID())
- .arg(nextRecording->GetTitle());
- VERBOSE(VB_GENERAL, msg);
+ if (nexttv->IsTunerLocked())
+ {
+ QString msg = QString("SUPPRESSED recording \"%1\" on channel: "
+ "%2 on cardid: %3, sourceid %4. Tuner "
+ "is locked by an external application.")
+ .arg(ri.GetTitle())
+ .arg(ri.GetChanID())
+ .arg(ri.GetCardID())
+ .arg(ri.GetSourceID());
+ QByteArray amsg = msg.toLocal8Bit();
+ VERBOSE(VB_GENERAL, msg.constData());
- QMutexLocker lockit(reclist_lock);
- nextRecording->SetRecordingStatus(rsTunerBusy);
- nextRecording->AddHistory(true);
- statuschanged = true;
- continue;
- }
+ QMutexLocker lockit(reclist_lock);
+ ri.SetRecordingStatus(rsTunerBusy);
+ ri.AddHistory(true);
+ statuschanged = true;
+ return false;
+ }
- nexttv = (*m_tvList)[nextRecording->GetCardID()];
- // cerr << "nexttv = " << nextRecording->GetCardID();
- // cerr << " title: " << nextRecording->GetTitle() << endl;
+ if ((prerollseconds > 0) && !IsBusyRecording(&ri))
+ {
+ // Will use pre-roll settings only if no other
+ // program is currently being recorded
+ secsleft -= prerollseconds;
+ }
- if (nextRecording->GetRecordingStatus() != rsTuning)
- {
- if (nexttv->IsTunerLocked())
- {
- msg = QString("SUPPRESSED recording \"%1\" on channel: "
- "%2 on cardid: %3, sourceid %4. Tuner "
- "is locked by an external application.")
- .arg(nextRecording->GetTitle())
- .arg(nextRecording->GetChanID())
- .arg(nextRecording->GetCardID())
- .arg(nextRecording->GetSourceID());
- QByteArray amsg = msg.toLocal8Bit();
- VERBOSE(VB_GENERAL, msg.constData());
+ //VERBOSE(VB_GENERAL, secsleft << " seconds until "
+ //<< ri.GetTitle());
- QMutexLocker lockit(reclist_lock);
- nextRecording->SetRecordingStatus(rsTunerBusy);
- nextRecording->AddHistory(true);
- statuschanged = true;
- continue;
- }
+ if (secsleft > 30)
+ return false;
- if (!IsBusyRecording(nextRecording))
- {
- // Will use pre-roll settings only if no other
- // program is currently being recorded
- secsleft -= prerollseconds;
- }
+ if (nexttv->IsWaking())
+ {
+ if (secsleft > 0)
+ {
+ VERBOSE(VB_SCHEDULE,
+ QString("WARNING: Slave Backend %1 has NOT come "
+ "back from sleep yet. Recording can "
+ "not begin yet for: %2")
+ .arg(nexttv->GetHostName())
+ .arg(ri.GetTitle()));
+ }
+ else if (nexttv->GetLastWakeTime().secsTo(curtime) > 300)
+ {
+ VERBOSE(VB_SCHEDULE,
+ QString("WARNING: Slave Backend %1 has NOT come "
+ "back from sleep yet. Setting slave "
+ "status to unknown and attempting "
+ "to reschedule around its tuners.")
+ .arg(nexttv->GetHostName()));
- //VERBOSE(VB_GENERAL, secsleft << " seconds until " << nextRecording->GetTitle());
+ QMap<int, EncoderLink *>::Iterator enciter =
+ m_tvList->begin();
+ for (; enciter != m_tvList->end(); ++enciter)
+ {
+ EncoderLink *enc = *enciter;
+ if (enc->GetHostName() == nexttv->GetHostName())
+ enc->SetSleepStatus(sStatus_Undefined);
+ }
- if (secsleft > 30)
- continue;
+ Reschedule(0);
+ }
- if (nexttv->IsWaking())
- {
- if (secsleft > 0)
- {
- VERBOSE(VB_SCHEDULE,
- QString("WARNING: Slave Backend %1 has NOT come "
- "back from sleep yet. Recording can "
- "not begin yet for: %2")
- .arg(nexttv->GetHostName())
- .arg(nextRecording->GetTitle()));
- }
- else if (nexttv->GetLastWakeTime().secsTo(curtime) > 300)
- {
- VERBOSE(VB_SCHEDULE,
- QString("WARNING: Slave Backend %1 has NOT come "
- "back from sleep yet. Setting slave "
- "status to unknown and attempting "
- "to reschedule around its tuners.")
- .arg(nexttv->GetHostName()));
+ return false;
+ }
- QMap<int, EncoderLink *>::Iterator enciter =
- m_tvList->begin();
- for (; enciter != m_tvList->end(); ++enciter)
- {
- EncoderLink *enc = *enciter;
- if (enc->GetHostName() == nexttv->GetHostName())
- enc->SetSleepStatus(sStatus_Undefined);
- }
+ int fsID = -1;
+ if (ri.GetPathname().isEmpty())
+ {
+ QMutexLocker lockit(reclist_lock);
+ QString recording_dir;
+ fsID = FillRecordingDir(
+ ri.GetTitle(),
+ ri.GetHostname(),
+ ri.GetStorageGroup(),
+ ri.GetRecordingStartTime(),
+ ri.GetRecordingEndTime(),
+ ri.GetCardID(),
+ recording_dir,
+ reclist);
+ ri.SetPathname(recording_dir);
+ }
- Reschedule(0);
- }
+ if (!recPendingList[schedid])
+ {
+ nexttv->RecordPending(&ri, max(secsleft, 0),
+ hasLaterList.contains(schedid));
+ recPendingList[schedid] = true;
+ }
- continue;
- }
+ if (secsleft > 0)
+ return false;
- if (nextRecording->GetPathname().isEmpty())
- {
- QMutexLocker lockit(reclist_lock);
- QString recording_dir;
- fsID = FillRecordingDir(
- nextRecording->GetTitle(),
- nextRecording->GetHostname(),
- nextRecording->GetStorageGroup(),
- nextRecording->GetRecordingStartTime(),
- nextRecording->GetRecordingEndTime(),
- nextRecording->GetCardID(),
- recording_dir,
- reclist);
- nextRecording->SetPathname(recording_dir);
- }
+ QDateTime recstartts = mythCurrentDateTime().addSecs(30);
+ recstartts.setTime(
+ QTime(recstartts.time().hour(), recstartts.time().minute()));
+ ri.SetRecordingStartTime(recstartts);
- if (!recPendingList[schedid])
- {
- nexttv->RecordPending(nextRecording, max(secsleft, 0),
- hasLaterList.contains(schedid));
- recPendingList[schedid] = true;
- }
+ QMutexLocker lockit(reclist_lock);
- if (secsleft > -2)
- continue;
+ QString details = QString("%1: channel %2 on cardid %3, sourceid %4")
+ .arg(ri.toString(ProgramInfo::kTitleSubtitle))
+ .arg(ri.GetChanID())
+ .arg(ri.GetCardID())
+ .arg(ri.GetSourceID());
- QDateTime recstartts = mythCurrentDateTime().addSecs(30);
- recstartts.setTime
- (QTime(recstartts.time().hour(), recstartts.time().minute()));
- nextRecording->SetRecordingStartTime(recstartts);
+ RecStatusTypes recStatus = rsOffLine;
+ if (schedulingEnabled && nexttv->IsConnected())
+ {
+ if (ri.GetRecordingStatus() == rsWillRecord)
+ {
+ recStatus = nexttv->StartRecording(&ri);
+ ri.AddHistory(false);
- QMutexLocker lockit(reclist_lock);
+ // activate auto expirer
+ if (expirer)
+ expirer->Update(ri.GetCardID(), fsID, true);
+ }
+ }
- details = QString("%1: channel %2 on cardid %3, sourceid %4")
- .arg(nextRecording->toString(ProgramInfo::kTitleSubtitle))
- .arg(nextRecording->GetChanID())
- .arg(nextRecording->GetCardID())
- .arg(nextRecording->GetSourceID());
- } // if (nextRecording->GetRecordingStatus() != rsTuning)
+ HandleRecordingStatusChange(ri, recStatus, details);
+ statuschanged = true;
- if (schedulingEnabled && nexttv->IsConnected())
- {
- RecStatusTypes recStatus;
+ return false;
+}
- if (nextRecording->GetRecordingStatus() == rsWillRecord)
- {
- recStatus = nexttv->StartRecording(nextRecording);
- nextRecording->AddHistory(false);
- if (expirer)
- {
- // activate auto expirer
- expirer->Update(nextRecording->GetCardID(), fsID, true);
- }
- }
- else
- recStatus = nexttv->GetRecordingStatus();
+void Scheduler::HandleRecordingStatusChange(
+ RecordingInfo &ri, RecStatusTypes recStatus, const QString &details)
+{
+ if (ri.GetRecordingStatus() == recStatus)
+ return;
- nextRecording->SetRecordingStatus(recStatus);
- if (recStatus == rsTuning)
- continue;
- }
- else
- nextRecording->SetRecordingStatus(rsOffLine);
- bool doSchedAfterStart =
- nextRecording->GetRecordingStatus() != rsRecording ||
- schedAfterStartMap[nextRecording->GetRecordingRuleID()] ||
- (nextRecording->GetParentRecordingRuleID() &&
- schedAfterStartMap[nextRecording->GetParentRecordingRuleID()]);
- nextRecording->AddHistory(doSchedAfterStart);
+ ri.SetRecordingStatus(recStatus);
- statuschanged = true;
+ if (rsTuning != recStatus)
+ {
+ bool doSchedAfterStart =
+ ((rsRecording != recStatus) && (rsTuning != recStatus)) ||
+ schedAfterStartMap[ri.GetRecordingRuleID()] ||
+ (ri.GetParentRecordingRuleID() &&
+ schedAfterStartMap[ri.GetParentRecordingRuleID()]);
+ ri.AddHistory(doSchedAfterStart);
+ }
- bool is_rec = (nextRecording->GetRecordingStatus() == rsRecording);
- msg = is_rec ?
- QString("Started recording") :
- QString("Canceled recording (%1)")
- .arg(toString(nextRecording->GetRecordingStatus(),
- nextRecording->GetRecordingRuleType()));
+ QString msg = (rsRecording == recStatus) ?
+ QString("Started recording") :
+ ((rsTuning == recStatus) ?
+ QString("Tuning recording") :
+ QString("Canceled recording (%1)")
+ .arg(toString(ri.GetRecordingStatus(), ri.GetRecordingRuleType())));
- VERBOSE(VB_GENERAL, QString("%1: %2").arg(msg).arg(details));
- gCoreContext->LogEntry("scheduler", LP_NOTICE, msg, details);
+ VERBOSE(VB_GENERAL, QString("%1: %2").arg(msg).arg(details));
+ gCoreContext->LogEntry("scheduler", LP_NOTICE, msg, details);
- if (is_rec)
- UpdateNextRecord();
+ if ((rsRecording == recStatus) || (rsTuning == recStatus))
+ {
+ UpdateNextRecord();
+ }
+ else if (rsFailed == recStatus)
+ {
+ MythEvent me(QString("FORCE_DELETE_RECORDING %1 %2")
+ .arg(ri.GetChanID())
+ .arg(ri.GetRecordingStartTime(ISODate)));
+ gCoreContext->dispatch(me);
+ }
+}
- if (nextRecording->GetRecordingStatus() == rsFailed)
+void Scheduler::HandleTuning(RecordingInfo &ri, bool &statuschanged)
+{
+ if (rsTuning != ri.GetRecordingStatus())
+ return;
+
+ // Determine current recording status
+ QMap<int, EncoderLink*>::iterator tvit = m_tvList->find(ri.GetCardID());
+ RecStatusTypes recStatus = rsTunerBusy;
+ if (tvit == m_tvList->end())
+ {
+ QString msg = QString("Invalid cardid (%1) for %2")
+ .arg(ri.GetCardID()).arg(ri.GetTitle());
+ VERBOSE(VB_GENERAL, LOC + msg);
+ }
+ else
+ {
+ recStatus = (*tvit)->GetRecordingStatus();
+ if (rsTuning == recStatus)
+ {
+ // If tuning is still taking place this long after we
+ // started give up on it so the scheduler can try to
+ // find another broadcast of the same material.
+ QDateTime curtime = QDateTime::currentDateTime();
+ if ((ri.GetRecordingStartTime().secsTo(curtime) > 180) &&
+ (ri.GetScheduledStartTime().secsTo(curtime) > 180))
{
- MythEvent me(QString("FORCE_DELETE_RECORDING %1 %2")
- .arg(nextRecording->GetChanID())
- .arg(nextRecording->GetRecordingStartTime(ISODate)));
- gCoreContext->dispatch(me);
+ recStatus = rsFailed;
}
}
+ }
- if (statuschanged)
+ // If the status has changed, handle it
+ if (rsTuning != recStatus)
+ {
+ QMutexLocker lockit(reclist_lock);
+
+ QString details = QString("%1: channel %2 on cardid %3, sourceid %4")
+ .arg(ri.toString(ProgramInfo::kTitleSubtitle))
+ .arg(ri.GetChanID()).arg(ri.GetCardID()).arg(ri.GetSourceID());
+ HandleRecordingStatusChange(ri, recStatus, details);
+ statuschanged = true;
+ }
+}
+
+void Scheduler::HandleIdleShutdown(
+ bool &blockShutdown, QDateTime &idleSince,
+ int prerollseconds, int idleTimeoutSecs, int idleWaitForRecordingTime)
+{
+ if ((idleTimeoutSecs <= 0) || (m_mainServer == NULL))
+ return;
+
+ // we release the block when a client connects
+ if (blockShutdown)
+ blockShutdown &= !m_mainServer->isClientConnected();
+ else
+ {
+ QDateTime curtime = QDateTime::currentDateTime();
+
+ // find out, if we are currently recording (or LiveTV)
+ bool recording = false;
+ QMap<int, EncoderLink *>::Iterator it;
+ for (it = m_tvList->begin(); (it != m_tvList->end()) &&
+ !recording; ++it)
{
- MythEvent me("SCHEDULE_CHANGE");
- gCoreContext->dispatch(me);
- idleSince = QDateTime();
+ if ((*it)->IsBusy())
+ recording = true;
}
- // if idletimeout is 0, the user disabled the auto-shutdown feature
- if ((idleTimeoutSecs > 0) && (m_mainServer != NULL))
+ if (!(m_mainServer->isClientConnected()) && !recording)
{
- // we release the block when a client connects
- if (blockShutdown)
- blockShutdown &= !m_mainServer->isClientConnected();
- else
+ // have we received a RESET_IDLETIME message?
+ resetIdleTime_lock.lock();
+ if (resetIdleTime)
{
- // find out, if we are currently recording (or LiveTV)
- bool recording = false;
- QMap<int, EncoderLink *>::Iterator it;
- for (it = m_tvList->begin(); (it != m_tvList->end()) &&
- !recording; ++it)
- {
- if ((*it)->IsBusy())
- recording = true;
- }
+ // yes - so reset the idleSince time
+ idleSince = QDateTime();
+ resetIdleTime = false;
+ }
+ resetIdleTime_lock.unlock();
- if (!(m_mainServer->isClientConnected()) && !recording)
+ if (!idleSince.isValid())
+ {
+ RecIter idleIter = reclist.begin();
+ for ( ; idleIter != reclist.end(); ++idleIter)
+ if ((*idleIter)->GetRecordingStatus() ==
+ rsWillRecord)
+ break;
+
+ if (idleIter != reclist.end())
{
- // have we received a RESET_IDLETIME message?
- resetIdleTime_lock.lock();
- if (resetIdleTime)
+ if (curtime.secsTo
+ ((*idleIter)->GetRecordingStartTime()) -
+ prerollseconds >
+ (idleWaitForRecordingTime * 60) +
+ idleTimeoutSecs)
{
- // yes - so reset the idleSince time
- idleSince = QDateTime();
- resetIdleTime = false;
+ idleSince = curtime;
}
- resetIdleTime_lock.unlock();
-
- if (!idleSince.isValid())
+ }
+ else
+ idleSince = curtime;
+ }
+ else
+ {
+ // is the machine already idling the timeout time?
+ if (idleSince.addSecs(idleTimeoutSecs) < curtime)
+ {
+ // are we waiting for shutdown?
+ if (m_isShuttingDown)
{
- RecIter idleIter = reclist.begin();
- for ( ; idleIter != reclist.end(); ++idleIter)
- if ((*idleIter)->GetRecordingStatus() ==
- rsWillRecord)
- break;
-
- if (idleIter != reclist.end())
+ // if we have been waiting more that 60secs then assume
+ // something went wrong so reset and try again
+ if (idleSince.addSecs(idleTimeoutSecs + 60) <
+ curtime)
{
- if (curtime.secsTo
- ((*idleIter)->GetRecordingStartTime()) -
- prerollseconds >
- (idleWaitForRecordingTime * 60) +
- idleTimeoutSecs)
- {
- idleSince = curtime;
- }
+ VERBOSE(VB_IMPORTANT, "Waited more than 60"
+ " seconds for shutdown to complete"
+ " - resetting idle time");
+ idleSince = QDateTime();
+ m_isShuttingDown = false;
}
- else
- idleSince = curtime;
}
- else
+ else if (!m_isShuttingDown &&
+ CheckShutdownServer(prerollseconds,
+ idleSince,
+ blockShutdown))
{
- // is the machine already idling the timeout time?
- if (idleSince.addSecs(idleTimeoutSecs) < curtime)
- {
- // are we waiting for shutdown?
- if (m_isShuttingDown)
- {
- // if we have been waiting more that 60secs then assume
- // something went wrong so reset and try again
- if (idleSince.addSecs(idleTimeoutSecs + 60) <
- curtime)
- {
- VERBOSE(VB_IMPORTANT, "Waited more than 60"
- " seconds for shutdown to complete"
- " - resetting idle time");
- idleSince = QDateTime();
- m_isShuttingDown = false;
- }
- }
- else if (!m_isShuttingDown &&
- CheckShutdownServer(prerollseconds,
- idleSince,
- blockShutdown))
- {
- ShutdownServer(prerollseconds, idleSince);
- }
- }
- else
- {
- int itime = idleSince.secsTo(curtime);
- QString msg;
- if (itime == 1)
- {
- msg = QString("I\'m idle now... shutdown will "
- "occur in %1 seconds.")
- .arg(idleTimeoutSecs);
- VERBOSE(VB_IMPORTANT, msg);
- MythEvent me(QString("SHUTDOWN_COUNTDOWN %1")
- .arg(idleTimeoutSecs));
- gCoreContext->dispatch(me);
- }
- else if (itime % 10 == 0)
- {
- msg = QString("%1 secs left to system "
- "shutdown!")
- .arg(idleTimeoutSecs - itime);
- VERBOSE(VB_IDLE, msg);
- MythEvent me(QString("SHUTDOWN_COUNTDOWN %1")
- .arg(idleTimeoutSecs - itime));
- gCoreContext->dispatch(me);
- }
- }
+ ShutdownServer(prerollseconds, idleSince);
}
}
else
{
- // not idle, make the time invalid
- if (idleSince.isValid())
+ int itime = idleSince.secsTo(curtime);
+ QString msg;
+ if (itime == 1)
{
- MythEvent me(QString("SHUTDOWN_COUNTDOWN -1"));
+ msg = QString("I\'m idle now... shutdown will "
+ "occur in %1 seconds.")
+ .arg(idleTimeoutSecs);
+ VERBOSE(VB_IMPORTANT, msg);
+ MythEvent me(QString("SHUTDOWN_COUNTDOWN %1")
+ .arg(idleTimeoutSecs));
gCoreContext->dispatch(me);
}
- idleSince = QDateTime();
+ else if (itime % 10 == 0)
+ {
+ msg = QString("%1 secs left to system "
+ "shutdown!")
+ .arg(idleTimeoutSecs - itime);
+ VERBOSE(VB_IDLE, msg);
+ MythEvent me(QString("SHUTDOWN_COUNTDOWN %1")
+ .arg(idleTimeoutSecs - itime));
+ gCoreContext->dispatch(me);
+ }
}
}
}
+ else
+ {
+ // not idle, make the time invalid
+ if (idleSince.isValid())
+ {
+ MythEvent me(QString("SHUTDOWN_COUNTDOWN -1"));
+ gCoreContext->dispatch(me);
+ }
+ idleSince = QDateTime();
+ }
}
}
+
//returns true, if the shutdown is not blocked
bool Scheduler::CheckShutdownServer(int prerollseconds, QDateTime &idleSince,
bool &blockShutdown)
@@ -2446,6 +2636,7 @@
RecordingInfo *pginfo = *recIter;
if ((pginfo->GetRecordingStatus() != rsRecording) &&
+ (pginfo->GetRecordingStatus() != rsTuning) &&
(pginfo->GetRecordingStatus() != rsWillRecord))
continue;