00001 #include <qapplication.h>
00002 #include <qfile.h>
00003 #include <qtextstream.h>
00004
00005 #include <iostream>
00006 #include <cstdlib>
00007 using namespace std;
00008 #include <unistd.h>
00009
00010 #include <exitcodes.h>
00011 #include <mythcontext.h>
00012 #include <mythdbcon.h>
00013 #include "libmythtv/programinfo.h"
00014 #include "libmythtv/jobqueue.h"
00015 #include "tv.h"
00016 #include "remoteutil.h"
00017 #include "compat.h"
00018
00019 void setGlobalSetting(const QString &key, const QString &value)
00020 {
00021 MSqlQuery query(MSqlQuery::InitCon());
00022 if (query.isConnected())
00023 {
00024 query.prepare("DELETE FROM settings WHERE value = :KEY;");
00025 query.bindValue(":KEY", key);
00026
00027 if (!query.exec() || !query.isActive())
00028 MythContext::DBError("Clear setting", query);
00029
00030 query.prepare("INSERT INTO settings ( value, data ) "
00031 "VALUES ( :VALUE, :DATA );");
00032 query.bindValue(":VALUE", key);
00033 query.bindValue(":DATA", value);
00034
00035 if (!query.exec() || !query.isActive())
00036 MythContext::DBError("Save new global setting", query);
00037 }
00038 else
00039 {
00040 VERBOSE(VB_IMPORTANT,
00041 QString("Database not open while trying to save setting: %1")
00042 .arg(key));
00043 }
00044 }
00045
00046 QString getGlobalSetting(const QString &key, const QString &defaultval)
00047 {
00048 QString value = defaultval;
00049
00050 MSqlQuery query(MSqlQuery::InitCon());
00051 if (query.isConnected())
00052 {
00053 query.prepare("SELECT data FROM settings WHERE value = :KEY AND "
00054 "hostname IS NULL;");
00055 query.bindValue(":KEY", key);
00056 query.exec();
00057 if (query.isActive() && query.size() > 0)
00058 {
00059 query.next();
00060 value = QString::fromUtf8(query.value(0).toString());
00061 }
00062 }
00063 else
00064 {
00065 VERBOSE(VB_IMPORTANT,
00066 QString("Database not open while trying to load setting: %1")
00067 .arg(key));
00068 }
00069
00070 return value;
00071 }
00072
00073 int lockShutdown()
00074 {
00075 VERBOSE(VB_GENERAL, "Mythshutdown: --lock");
00076
00077 MSqlQuery query(MSqlQuery::InitCon());
00078
00079
00080 int tries = 0;
00081 while (!query.exec("LOCK TABLE settings WRITE;") && tries < 5)
00082 {
00083 VERBOSE(VB_GENERAL, "Waiting for lock on setting table");
00084 sleep(1);
00085 tries++;
00086 }
00087
00088 if (tries >= 5)
00089 {
00090 VERBOSE(VB_GENERAL, "Waited too long to obtain lock on setting table");
00091 return 1;
00092 }
00093
00094
00095 query.exec("SELECT * FROM settings "
00096 "WHERE value = 'MythShutdownLock' AND hostname IS NULL;");
00097
00098 if (query.size() < 1)
00099 {
00100
00101 query.exec("INSERT INTO settings (value, data) "
00102 "VALUES ('MythShutdownLock', '1');");
00103 }
00104 else
00105 {
00106
00107 query.exec("UPDATE settings SET data = data + 1 "
00108 "WHERE value = 'MythShutdownLock' AND hostname IS NULL;");
00109 }
00110
00111
00112 query.exec("UNLOCK TABLES;");
00113
00114 return 0;
00115 }
00116
00117 int unlockShutdown()
00118 {
00119 VERBOSE(VB_GENERAL, "Mythshutdown: --unlock");
00120
00121 MSqlQuery query(MSqlQuery::InitCon());
00122
00123
00124 int tries = 0;
00125 while (!query.exec("LOCK TABLE settings WRITE;") && tries < 5)
00126 {
00127 VERBOSE(VB_GENERAL, "Waiting for lock on setting table");
00128 sleep(1);
00129 tries++;
00130 }
00131
00132 if (tries >= 5)
00133 {
00134 VERBOSE(VB_GENERAL, "Waited too long to obtain lock on setting table");
00135 return 1;
00136 }
00137
00138
00139 query.exec("SELECT * FROM settings "
00140 "WHERE value = 'MythShutdownLock' AND hostname IS NULL;");
00141
00142 if (query.size() < 1)
00143 {
00144
00145 query.exec("INSERT INTO settings (value, data) "
00146 "VALUES ('MythShutdownLock', '0');");
00147 }
00148 else
00149 {
00150
00151 query.exec("UPDATE settings SET data = GREATEST(0, data - 1) "
00152 "WHERE value = 'MythShutdownLock' AND hostname IS NULL;");
00153 }
00154
00155
00156 query.exec("UNLOCK TABLES;");
00157
00158
00159 RemoteSendMessage("RESET_IDLETIME");
00160
00161 return 0;
00162 }
00163
00164 bool isRunning(QString program)
00165 {
00166 QString sCommand = QString("ret=`ps cax | grep -c %1`; exit $ret").arg(program);
00167 int res = system(sCommand.ascii());
00168 if (WIFEXITED(res))
00169 res = WEXITSTATUS(res);
00170
00171 return res;
00172 }
00173
00174 QDateTime getDailyWakeupTime(QString sPeriod)
00175 {
00176 QString sTime = getGlobalSetting(sPeriod, "00:00");
00177 QTime tTime = QTime::fromString(sTime);
00178 QDateTime dtDateTime = QDateTime(QDate::currentDate(), tTime);
00179
00180 return dtDateTime;
00181 }
00182
00183 bool isRecording()
00184 {
00185 if (!gContext->IsConnectedToMaster())
00186 {
00187 VERBOSE(VB_IMPORTANT, "isRecording: Attempting to connect to master server...");
00188 if (!gContext->ConnectToMasterServer(false))
00189 {
00190 VERBOSE(VB_IMPORTANT, "isRecording: Could not connect to master server!");
00191 return false;
00192 }
00193 }
00194
00195 return RemoteGetRecordingStatus(NULL, false);
00196 }
00197
00198 int getStatus(bool bWantRecStatus)
00199 {
00200 VERBOSE(VB_GENERAL, "Mythshutdown: --status");
00201
00202 int res = 0;
00203
00204 if (isRunning("mythtranscode"))
00205 {
00206 VERBOSE(VB_IMPORTANT, "Transcoding in progress...");
00207 res += 1;
00208 }
00209
00210 if (isRunning("mythcommflag"))
00211 {
00212 VERBOSE(VB_IMPORTANT, "Commercial Flagging in progress...");
00213 res += 2;
00214 }
00215
00216 if (isRunning("mythfilldatabas"))
00217 {
00218 VERBOSE(VB_IMPORTANT, "Grabbing EPG data in progress...");
00219 res += 4;
00220 }
00221
00222 if (bWantRecStatus && isRecording())
00223 {
00224 VERBOSE(VB_IMPORTANT, "Recording in progress...");
00225 res += 8;
00226 }
00227
00228 if (getGlobalSetting("MythShutdownLock", "0") != "0")
00229 {
00230 VERBOSE(VB_IMPORTANT, "Shutdown is locked");
00231 res += 16;
00232 }
00233
00234 if (JobQueue::HasRunningOrPendingJobs(15))
00235 {
00236 VERBOSE(VB_IMPORTANT, "Has queued or pending jobs");
00237 res += 32;
00238 }
00239
00240 QDateTime dtPeriod1Start = getDailyWakeupTime("DailyWakeupStartPeriod1");
00241 QDateTime dtPeriod1End = getDailyWakeupTime("DailyWakeupEndPeriod1");
00242 QDateTime dtPeriod2Start = getDailyWakeupTime("DailyWakeupStartPeriod2");
00243 QDateTime dtPeriod2End = getDailyWakeupTime("DailyWakeupEndPeriod2");
00244 QDateTime dtCurrent = QDateTime::currentDateTime();
00245
00246
00247 if (dtPeriod1End < dtPeriod1Start)
00248 {
00249 if (dtCurrent > dtPeriod1End)
00250 dtPeriod1End = dtPeriod1End.addDays(1);
00251 else
00252 dtPeriod1Start = dtPeriod1Start.addDays(-1);
00253 }
00254
00255 if (dtPeriod2End < dtPeriod2Start)
00256 {
00257 if (dtCurrent > dtPeriod2End)
00258 dtPeriod2End = dtPeriod2End.addDays(1);
00259 else
00260 dtPeriod2Start = dtPeriod2Start.addDays(-1);
00261 }
00262
00263
00264 if (dtPeriod1Start != dtPeriod1End)
00265 {
00266 if (dtCurrent >= dtPeriod1Start && dtCurrent <= dtPeriod1End)
00267 {
00268 VERBOSE(VB_IMPORTANT, "In a daily wakeup period (1).");
00269 res |= 64;
00270 }
00271 }
00272
00273 if (dtPeriod2Start != dtPeriod2End)
00274 {
00275 if (dtCurrent >= dtPeriod2Start && dtCurrent <= dtPeriod2End)
00276 {
00277 VERBOSE(VB_IMPORTANT, "In a daily wakeup period (2).");
00278 res |= 64;
00279 }
00280 }
00281
00282
00283
00284 if (dtPeriod1Start != dtPeriod1End)
00285 {
00286 int delta = dtCurrent.secsTo(dtPeriod1Start);
00287 if (delta >= 0 && delta <= 15 * 60)
00288 {
00289 VERBOSE(VB_IMPORTANT, "About to start daily wakeup period (1)");
00290 res |= 128;
00291 }
00292 }
00293
00294 if (dtPeriod2Start != dtPeriod2End)
00295 {
00296 int delta = dtCurrent.secsTo(dtPeriod2Start);
00297 if (delta >= 0 && delta <= 15 * 60)
00298 {
00299 VERBOSE(VB_IMPORTANT, "About to start daily wakeup period (2)");
00300 res |= 128;
00301 }
00302 }
00303
00304 if (isRunning("mythtv-setup"))
00305 {
00306 VERBOSE(VB_IMPORTANT, "Setup is running...");
00307 res = 255;
00308 }
00309
00310 VERBOSE(VB_GENERAL, "Mythshutdown: --status returned: " << res);
00311
00312 return res;
00313 }
00314
00315 int checkOKShutdown(bool bWantRecStatus)
00316 {
00317
00318
00319 VERBOSE(VB_GENERAL, "Mythshutdown: --check");
00320
00321 int res = getStatus(bWantRecStatus);
00322
00323 if (res > 0)
00324 {
00325 VERBOSE(VB_IMPORTANT, "Not OK to shutdown");
00326 res = 1;
00327 }
00328 else
00329 {
00330 VERBOSE(VB_IMPORTANT, "OK to shutdown");
00331 res = 0;
00332 }
00333
00334 VERBOSE(VB_GENERAL, "Mythshutdown: --check returned: " << res);
00335
00336 return res;
00337 }
00338
00339 int setWakeupTime(QString sWakeupTime)
00340 {
00341 VERBOSE(VB_GENERAL, "Mythshutdown: --setwakeup");
00342
00343 VERBOSE(VB_IMPORTANT, "Mythshutdown: wakeup time given is: " << sWakeupTime);
00344
00345
00346 QDateTime dtWakeupTime;
00347 dtWakeupTime = QDateTime::fromString(sWakeupTime, Qt::ISODate);
00348
00349 if (!dtWakeupTime.isValid())
00350 {
00351 VERBOSE(VB_IMPORTANT, QString("Mythshutdown: --setwakeup invalid date "
00352 "format (%1)\n\t\t\t"
00353 "must be yyyy-MM-ddThh:mm:ss")
00354 .arg(sWakeupTime));
00355 return 1;
00356 }
00357
00358 setGlobalSetting("MythShutdownNextScheduled", dtWakeupTime.toString(Qt::ISODate));
00359
00360 return 0;
00361 }
00362
00363 int setScheduledWakeupTime()
00364 {
00365 typedef struct
00366 {
00367 QString channel, title, subtitle;
00368 QDateTime startTime, endTime;
00369 } ProgramDetail;
00370
00371 if (!gContext->IsConnectedToMaster())
00372 {
00373 VERBOSE(VB_IMPORTANT, "setScheduledWakeupTime: Attempting to connect to master server...");
00374 if (!gContext->ConnectToMasterServer(false))
00375 {
00376 VERBOSE(VB_IMPORTANT, "setScheduledWakeupTime: Could not connect to master server!");
00377 return false;
00378 }
00379 }
00380
00381 QDateTime m_nextRecordingStart = QDateTime();
00382
00383 ProgramList *progList = new ProgramList(true);
00384 ProgramInfo *progInfo;
00385
00386 if (progList->FromScheduler())
00387 {
00388 if (progList->count() > 0)
00389 {
00390 VERBOSE(VB_IMPORTANT, "setScheduledWakeupTime: At least one scheduled recording found.");
00391
00392 for (progInfo = progList->first(); progInfo; progInfo = progList->next())
00393 {
00394 if (progInfo->recstatus == rsWillRecord)
00395 {
00396 if (m_nextRecordingStart.isNull() ||
00397 m_nextRecordingStart > progInfo->recstartts)
00398 {
00399 m_nextRecordingStart = progInfo->recstartts;
00400 }
00401 }
00402 }
00403
00404
00405 for (progInfo = progList->first(); progInfo; progInfo = progList->next())
00406 {
00407 if (progInfo->recstatus == rsWillRecord)
00408 {
00409 if (progInfo->recstartts == m_nextRecordingStart)
00410 {
00411 ProgramDetail *prog = new ProgramDetail;
00412 prog->channel = progInfo->channame;
00413 prog->title = progInfo->title;
00414 prog->subtitle = progInfo->subtitle;
00415 prog->startTime = progInfo->recstartts;
00416 prog->endTime = progInfo->recendts;
00417 }
00418 }
00419 }
00420 }
00421 }
00422
00423 delete progList;
00424
00425
00426 if (!m_nextRecordingStart.isNull())
00427 {
00428 int m_preRollSeconds = gContext->GetNumSetting("RecordPreRoll");
00429 QDateTime restarttime = m_nextRecordingStart.addSecs((-1) * m_preRollSeconds);
00430
00431 int add = gContext->GetNumSetting("StartupSecsBeforeRecording", 240);
00432 if (add)
00433 restarttime = restarttime.addSecs((-1) * add);
00434
00435 setWakeupTime(restarttime.toString(Qt::ISODate));
00436
00437 return true;
00438 }
00439 return false;
00440 }
00441
00442 int shutdown()
00443 {
00444 VERBOSE(VB_GENERAL, "Mythshutdown: --shutdown");
00445
00446
00447 QDateTime dtPeriod1Start = getDailyWakeupTime("DailyWakeupStartPeriod1");
00448 QDateTime dtPeriod1End = getDailyWakeupTime("DailyWakeupEndPeriod1");
00449 QDateTime dtPeriod2Start = getDailyWakeupTime("DailyWakeupStartPeriod2");
00450 QDateTime dtPeriod2End = getDailyWakeupTime("DailyWakeupEndPeriod2");
00451 QDateTime dtCurrent = QDateTime::currentDateTime();
00452 QDateTime dtNextDailyWakeup = QDateTime();
00453
00454
00455 if (dtPeriod1End < dtPeriod1Start)
00456 {
00457 if (dtCurrent > dtPeriod1End)
00458 dtPeriod1End = dtPeriod1End.addDays(1);
00459 else
00460 dtPeriod1Start = dtPeriod1Start.addDays(-1);
00461 }
00462
00463 if (dtPeriod2End < dtPeriod2Start)
00464 {
00465 if (dtCurrent > dtPeriod2End)
00466 dtPeriod2End = dtPeriod2End.addDays(1);
00467 else
00468 dtPeriod2Start = dtPeriod2Start.addDays(-1);
00469 }
00470
00471
00472 if (dtPeriod1Start != dtPeriod1End)
00473 {
00474 if (dtCurrent < dtPeriod1Start)
00475 {
00476 VERBOSE(VB_IMPORTANT, "daily wakeup today at " <<
00477 dtPeriod1Start.toString("hh:mm:ss"));
00478 dtNextDailyWakeup = dtPeriod1Start;
00479 }
00480 }
00481
00482
00483 if (!dtNextDailyWakeup.isValid() && dtPeriod2Start != dtPeriod2End)
00484 {
00485 if (dtCurrent < dtPeriod2Start)
00486 {
00487 VERBOSE(VB_IMPORTANT, "daily wakeup today at " <<
00488 dtPeriod2Start.toString("hh:mm:ss"));
00489 dtNextDailyWakeup = dtPeriod2Start;
00490 }
00491 }
00492
00493
00494
00495 if (!dtNextDailyWakeup.isValid())
00496 {
00497 if (dtPeriod1Start != dtPeriod1End)
00498 dtNextDailyWakeup = dtPeriod1Start;
00499 else if (dtPeriod2Start != dtPeriod2End)
00500 dtNextDailyWakeup = dtPeriod2Start;
00501
00502 if (dtNextDailyWakeup.isValid())
00503 {
00504 dtNextDailyWakeup = dtNextDailyWakeup.addDays(1);
00505
00506 VERBOSE(VB_IMPORTANT, "next daily wakeup is tomorrow at " <<
00507 dtNextDailyWakeup.toString("hh:mm:ss"));
00508 }
00509 }
00510
00511
00512 if (!dtNextDailyWakeup.isValid())
00513 VERBOSE(VB_IMPORTANT,"no daily wakeup times are set");
00514
00515
00516 QDateTime dtNextRecordingStart = QDateTime();
00517 QString s = getGlobalSetting("MythShutdownNextScheduled", "");
00518 if (s != "")
00519 dtNextRecordingStart = QDateTime::fromString(s, Qt::ISODate);
00520
00521 if (!dtNextRecordingStart.isValid())
00522 VERBOSE(VB_IMPORTANT,"no recording time is set");
00523 else
00524 VERBOSE(VB_IMPORTANT, "recording scheduled at: " <<
00525 dtNextRecordingStart.toString(Qt::ISODate));
00526
00527
00528 if (dtNextRecordingStart.isValid())
00529 {
00530 int delta = dtCurrent.secsTo(dtNextRecordingStart);
00531
00532 if (delta < 0)
00533 {
00534 VERBOSE(VB_IMPORTANT, "scheduled recording time has already passed. "
00535 "schedule deleted");
00536
00537 dtNextRecordingStart = QDateTime();
00538 setGlobalSetting("MythShutdownNextScheduled", "");
00539 }
00540 }
00541
00542 QDateTime dtWakeupTime = QDateTime();
00543
00544
00545
00546
00547
00548 if (!dtNextRecordingStart.isValid() && !dtNextDailyWakeup.isValid())
00549 {
00550 dtWakeupTime = QDateTime();
00551 VERBOSE(VB_IMPORTANT, "no wake up time set and no scheduled program");
00552 }
00553
00554
00555
00556 if (dtNextRecordingStart.isValid() && !dtNextDailyWakeup.isValid())
00557 {
00558 dtWakeupTime = dtNextRecordingStart;
00559 VERBOSE(VB_IMPORTANT, "will wake up at next scheduled program");
00560 }
00561
00562
00563
00564 if (!dtNextRecordingStart.isValid() && dtNextDailyWakeup.isValid())
00565 {
00566 dtWakeupTime = dtNextDailyWakeup;
00567 VERBOSE(VB_IMPORTANT, "will wake up at next daily wakeup");
00568 }
00569
00570
00571
00572
00573 if (dtNextRecordingStart.isValid() && dtNextDailyWakeup.isValid())
00574 {
00575 if (dtNextDailyWakeup < dtNextRecordingStart)
00576 {
00577 VERBOSE(VB_IMPORTANT, "program is scheduled but will wake up "
00578 "at next daily wakeup");
00579 dtWakeupTime = dtNextDailyWakeup;
00580 }
00581 else
00582 {
00583 VERBOSE(VB_IMPORTANT, "daily wakeup is set but will wake up "
00584 "at next scheduled program");
00585 dtWakeupTime = dtNextRecordingStart;
00586 }
00587 }
00588
00589
00590 setGlobalSetting("MythShutdownWakeupTime", dtWakeupTime.toString(Qt::ISODate));
00591
00592
00593
00594
00595 int shutdownmode = 0;
00596 QString nvramRestartCmd =
00597 gContext->GetSetting("MythShutdownNvramRestartCmd", "");
00598
00599 if (dtWakeupTime.isValid())
00600 {
00601
00602 if (dtCurrent.secsTo(dtWakeupTime) > 15 * 60)
00603 {
00604 QString nvramCommand = gContext->GetSetting("MythShutdownNvramCmd",
00605 "/usr/bin/nvram-wakeup --settime $time");
00606
00607 QString wakeup_timeformat = gContext->GetSetting("MythShutdownWakeupTimeFmt", "time_t");
00608
00609 if (wakeup_timeformat == "time_t")
00610 {
00611 QString time_ts;
00612 nvramCommand.replace("$time", time_ts.setNum(dtWakeupTime.toTime_t()));
00613 }
00614 else
00615 nvramCommand.replace("$time", dtWakeupTime.toString(wakeup_timeformat));
00616
00617 VERBOSE(VB_IMPORTANT, QString("sending command to set time in bios\n\t\t\t%1")
00618 .arg(nvramCommand));
00619
00620 shutdownmode = system(nvramCommand);
00621 if (WIFEXITED(shutdownmode))
00622 shutdownmode = WEXITSTATUS(shutdownmode);
00623
00624 VERBOSE(VB_IMPORTANT, QString("%1 exited with code %2").arg(nvramCommand)
00625 .arg(shutdownmode));
00626
00627 if (shutdownmode == 2)
00628 {
00629 VERBOSE(VB_IMPORTANT, "nvram-wakeup failed to set time in bios");
00630 return 1;
00631 }
00632
00633
00634
00635 if (nvramRestartCmd == "")
00636 shutdownmode = 0;
00637 else
00638 shutdownmode = 1;
00639 }
00640 else
00641 {
00642 VERBOSE(VB_IMPORTANT, "The next wakeup time is less than 15 mins away,"
00643 "not shutting down");
00644 return 0;
00645 }
00646 }
00647
00648 int res = 0;
00649
00650 switch (shutdownmode)
00651 {
00652 case 0:
00653 {
00654 VERBOSE(VB_IMPORTANT, "everything looks fine, shutting down ...");
00655 QString poweroffCmd =
00656 gContext->GetSetting("MythShutdownPoweroff", "/sbin/poweroff");
00657 VERBOSE(VB_IMPORTANT, "..");
00658 VERBOSE(VB_IMPORTANT, ".");
00659 VERBOSE(VB_IMPORTANT, "shutting down ...");
00660
00661 system(poweroffCmd);
00662 res = 0;
00663 break;
00664 }
00665 case 1:
00666 {
00667 VERBOSE(VB_IMPORTANT, "everything looks fine, but reboot is needed");
00668 VERBOSE(VB_IMPORTANT, "sending command to bootloader ...");
00669 VERBOSE(VB_IMPORTANT, nvramRestartCmd);
00670
00671 system(nvramRestartCmd);
00672
00673 VERBOSE(VB_IMPORTANT, "..");
00674 VERBOSE(VB_IMPORTANT, ".");
00675 VERBOSE(VB_IMPORTANT, "rebooting ...");
00676
00677 QString rebootCmd =
00678 gContext->GetSetting("MythShutdownReboot", "/sbin/reboot");
00679 system(rebootCmd);
00680 res = 0;
00681 break;
00682 }
00683 default:
00684 VERBOSE(VB_IMPORTANT, "panic. invalid shutdown mode, do nothing");
00685 res = 1;
00686 break;
00687 }
00688
00689 return res;
00690 }
00691
00692 int startup()
00693 {
00694 VERBOSE(VB_GENERAL, "Mythshutdown: --startup");
00695
00696 int res = 0;
00697 QDateTime startupTime = QDateTime();
00698 QString s = getGlobalSetting("MythshutdownWakeupTime", "");
00699 if (s != "")
00700 startupTime = QDateTime::fromString(s, Qt::ISODate);
00701
00702
00703 if (!startupTime.isValid())
00704 res = 1;
00705 else
00706 {
00707
00708
00709
00710 int delta = startupTime.secsTo(QDateTime::currentDateTime());
00711 if (delta < 0)
00712 delta = -delta;
00713
00714 if (delta < 15 * 60)
00715 res = 0;
00716 else
00717 res = 1;
00718 }
00719
00720 if (res)
00721 VERBOSE(VB_IMPORTANT, "looks like we were started manually" << res);
00722 else
00723 VERBOSE(VB_IMPORTANT, "looks like we were started automatically" << res);
00724
00725
00726 VERBOSE(VB_GENERAL, "Mythshutdown: --startup returned: " << res);
00727
00728 return res;
00729 }
00730
00731 void showUsage()
00732 {
00733 cout << "Usage of mythshutdown\n";
00734 cout << "-w/--setwakeup time (sets the wakeup time. time=yyyy-MM-ddThh:mm:ss\n";
00735 cout << " doesn't write it into nvram)\n";
00736 cout << "-t/--setscheduledwakeup (sets the wakeup time to the next scheduled recording)\n";
00737 cout << "-q/--shutdown (set nvram-wakeup time and shutdown)\n";
00738 cout << "-x/--safeshutdown (equal to -c -t -q. check shutdown possible, set\n";
00739 cout <<" scheduled wakeup and shutdown)\n";
00740 cout << "-p/--startup (check startup. check will return 0 if automatic\n";
00741 cout << " 1 for manually)\n";
00742 cout << "-c/--check flag (check shutdown possible\n";
00743 cout << " flag is 0 - don't check recording status\n";
00744 cout << " 1 - do check recording status (default)\n";
00745 cout << " returns 0 ok to shutdown\n";
00746 cout << " 1 reset idle check)\n";
00747 cout << "-l/--lock (disable shutdown. check will return 1.)\n";
00748 cout << "-u/--unlock (enable shutdown. check will return 0)\n";
00749 cout << "-s/--status flag (returns a code indicating the current status)\n";
00750 cout << " flag is 0 - don't check recording status\n";
00751 cout << " 1 - do check recording status (default)\n";
00752 cout << " 0 - Idle\n";
00753 cout << " 1 - Transcoding\n";
00754 cout << " 2 - Commercial Flagging\n";
00755 cout << " 4 - Grabbing EPG data\n";
00756 cout << " 8 - Recording - only valid if flag is 1\n";
00757 cout << " 16 - Locked\n";
00758 cout << " 32 - Jobs running or pending\n";
00759 cout << " 64 - In a daily wakeup/shutdown period\n";
00760 cout << " 128 - Less than 15 minutes to next wakeup period\n";
00761 cout << " 255 - Setup is running\n";
00762 cout << "-v/--verbose debug-level (Use '-v help' for level info\n";
00763 cout << "-h/--help (shows this usage)\n";
00764 }
00765
00766 int main(int argc, char **argv)
00767 {
00768
00769 print_verbose_messages = VB_NONE;
00770
00771 QApplication a(argc, argv, false);
00772
00773
00774 bool bLockShutdown = false;
00775 bool bUnlockShutdown = false;
00776 bool bCheckOKShutdown = false;
00777 bool bStartup = false;
00778 bool bShutdown = false;
00779 bool bGetStatus = false;
00780 bool bSetWakeupTime = false;
00781 QString sWakeupTime = "";
00782 bool bShowUsage = false;
00783 bool bSetScheduledWakeupTime = false;
00784 bool bCheckAndShutdown = false;
00785 bool bWantRecStatus = true;
00786
00787
00788 for (int argpos = 1; argpos < a.argc(); ++argpos)
00789 {
00790 if (!strcmp(a.argv()[argpos],"-v") ||
00791 !strcmp(a.argv()[argpos],"--verbose"))
00792 {
00793 if (a.argc()-1 > argpos)
00794 {
00795 if (parse_verbose_arg(a.argv()[argpos+1]) ==
00796 GENERIC_EXIT_INVALID_CMDLINE)
00797 return FRONTEND_EXIT_INVALID_CMDLINE;
00798 ++argpos;
00799 }
00800 else
00801 {
00802 cerr << "Missing argument to -v/--verbose option\n";
00803 return FRONTEND_EXIT_INVALID_CMDLINE;
00804 }
00805 }
00806
00807 else if (!strcmp(a.argv()[argpos],"-l") ||
00808 !strcmp(a.argv()[argpos],"--lock"))
00809 {
00810 bLockShutdown = true;
00811 }
00812 else if (!strcmp(a.argv()[argpos],"-u") ||
00813 !strcmp(a.argv()[argpos],"--unlock"))
00814 {
00815 bUnlockShutdown = true;
00816 }
00817 else if (!strcmp(a.argv()[argpos],"-c") ||
00818 !strcmp(a.argv()[argpos],"--check"))
00819 {
00820 bCheckOKShutdown = true;
00821 if (a.argc() - 1 > argpos)
00822 {
00823 QString s = a.argv()[argpos+1];
00824 if (!s.startsWith("-"))
00825 {
00826 if (s == "0")
00827 bWantRecStatus = false;
00828 ++argpos;
00829 }
00830 }
00831 }
00832 else if (!strcmp(a.argv()[argpos],"-s") ||
00833 !strcmp(a.argv()[argpos],"--status"))
00834 {
00835 bGetStatus = true;
00836 if (a.argc() - 1 > argpos)
00837 {
00838 QString s = a.argv()[argpos+1];
00839 if (!s.startsWith("-"))
00840 {
00841 if (s == "0")
00842 bWantRecStatus = false;
00843 ++argpos;
00844 }
00845 }
00846 }
00847 else if (!strcmp(a.argv()[argpos],"-w") ||
00848 !strcmp(a.argv()[argpos],"--setwakeup"))
00849 {
00850 if (a.argc() - 1 > argpos)
00851 {
00852 sWakeupTime = a.argv()[argpos+1];
00853 ++argpos;
00854 }
00855 else
00856 {
00857 cout << "mythshutdown: Missing argument to "
00858 "-w/--setwakeup option" << endl;
00859 return FRONTEND_EXIT_INVALID_CMDLINE;
00860 }
00861
00862 bSetWakeupTime = true;
00863 }
00864 else if (!strcmp(a.argv()[argpos],"-q") ||
00865 !strcmp(a.argv()[argpos],"--shutdown"))
00866 {
00867 bShutdown = true;
00868 }
00869 else if (!strcmp(a.argv()[argpos],"-p") ||
00870 !strcmp(a.argv()[argpos],"--startup"))
00871 {
00872 bStartup = true;
00873 }
00874 else if (!strcmp(a.argv()[argpos],"-h") ||
00875 !strcmp(a.argv()[argpos],"--help"))
00876 {
00877 bShowUsage = true;
00878 }
00879 else if (!strcmp(a.argv()[argpos],"-t") ||
00880 !strcmp(a.argv()[argpos],"--setscheduledwakeup"))
00881 {
00882 bSetScheduledWakeupTime = true;
00883 }
00884 else if (!strcmp(a.argv()[argpos],"-x") ||
00885 !strcmp(a.argv()[argpos],"--safeshutdown"))
00886 {
00887 bCheckAndShutdown = true;
00888 }
00889
00890 else
00891 {
00892 cout << "Invalid argument: " << a.argv()[argpos] << endl;
00893 showUsage();
00894 return FRONTEND_EXIT_INVALID_CMDLINE;
00895 }
00896 }
00897
00898
00899 gContext = new MythContext(MYTH_BINARY_VERSION);
00900 if (!gContext->Init(false))
00901 {
00902 cout << "mythshutdown: Could not initialize myth context. "
00903 "Exiting." << endl;
00904 return FRONTEND_EXIT_NO_MYTHCONTEXT;
00905 }
00906
00907
00908 int res = 0;
00909
00910 if (bShowUsage)
00911 showUsage();
00912 else if (bLockShutdown)
00913 res = lockShutdown();
00914 else if (bUnlockShutdown)
00915 res = unlockShutdown();
00916 else if (bCheckOKShutdown)
00917 res = checkOKShutdown(bWantRecStatus);
00918 else if (bSetScheduledWakeupTime)
00919 res = setScheduledWakeupTime();
00920 else if (bStartup)
00921 res = startup();
00922 else if (bShutdown)
00923 res = shutdown();
00924 else if (bGetStatus)
00925 res = getStatus(bWantRecStatus);
00926 else if (bSetWakeupTime)
00927 res = setWakeupTime(sWakeupTime);
00928 else if (bCheckAndShutdown)
00929 {
00930 res = checkOKShutdown(true);
00931 if (res == 0)
00932 {
00933 res = setScheduledWakeupTime();
00934 res = shutdown();
00935 }
00936 }
00937 else
00938 showUsage();
00939
00940 delete gContext;
00941
00942 return res;
00943 }
00944