int run_backend(const MythCommandLineParser &cmdline) { if (!setup_context(cmdline)) return GENERIC_EXIT_NO_MYTHCONTEXT; bool ismaster = gCoreContext->IsMasterHost(); if (!UpgradeTVDatabaseSchema(ismaster, ismaster)) { VERBOSE(VB_IMPORTANT, "Couldn't upgrade database to new schema"); return GENERIC_EXIT_DB_OUTOFDATE; } /////////////////////////////////////////// g_pUPnp = new MediaServer(ismaster, !cmdline.IsUPnPEnabled() ); if (!ismaster) { int ret = connect_to_master(); if (ret != GENERIC_EXIT_OK) return ret; } QString myip = gCoreContext->GetSetting("BackendServerIP"); int port = gCoreContext->GetNumSetting("BackendServerPort", 6543); if (myip.isEmpty()) { cerr << "No setting found for this machine's BackendServerIP.\n" << "Please run setup on this machine and modify the first page\n" << "of the general settings.\n"; return GENERIC_EXIT_SETUP_ERROR; } MythSystemEventHandler *sysEventHandler = new MythSystemEventHandler(); if (ismaster) { VERBOSE(VB_GENERAL, LOC + "Starting up as the master server."); gCoreContext->LogEntry("mythbackend", LP_INFO, "MythBackend started as master server", ""); } else { VERBOSE(VB_GENERAL, LOC + "Running as a slave backend."); gCoreContext->LogEntry("mythbackend", LP_INFO, "MythBackend started as a slave backend", ""); } print_warnings(cmdline); bool fatal_error = false; bool runsched = setupTVs(ismaster, fatal_error); if (fatal_error) { delete sysEventHandler; return GENERIC_EXIT_SETUP_ERROR; } if (ismaster) { if (runsched) { sched = new Scheduler(true, &tvList); int err = sched->GetError(); if (err) return err; if (!cmdline.IsSchedulerEnabled()) sched->DisableScheduling(); } if (cmdline.IsHouseKeeperEnabled()) housekeeping = new HouseKeeper(true, ismaster, sched); if (cmdline.IsAutoExpirerEnabled()) { expirer = new AutoExpire(&tvList); if (sched) sched->SetExpirer(expirer); } } else if (cmdline.IsHouseKeeperEnabled()) { housekeeping = new HouseKeeper(true, ismaster, NULL); } if (cmdline.IsJobQueueEnabled()) jobqueue = new JobQueue(ismaster); // Setup status server HttpStatus *httpStatus = NULL; HttpServer *pHS = g_pUPnp->GetHttpServer(); if (pHS) { VERBOSE(VB_IMPORTANT, "Main::Registering HttpStatus Extension"); httpStatus = new HttpStatus(&tvList, sched, expirer, ismaster); if (httpStatus) pHS->RegisterExtension(httpStatus); } VERBOSE(VB_IMPORTANT, QString("Enabled verbose msgs: %1") .arg(verboseString)); MainServer *mainServer = new MainServer( ismaster, port, &tvList, sched, expirer); int exitCode = mainServer->GetExitCode(); if (exitCode != GENERIC_EXIT_OK) { VERBOSE(VB_IMPORTANT, "Backend exiting, MainServer initialization " "error."); delete mainServer; return exitCode; } if (httpStatus && mainServer) httpStatus->SetMainServer(mainServer); StorageGroup::CheckAllStorageGroupDirs(); if (gCoreContext->IsMasterBackend()) SendMythSystemEvent("MASTER_STARTED"); /////////////////////////////// /////////////////////////////// exitCode = qApp->exec(); /////////////////////////////// /////////////////////////////// if (gCoreContext->IsMasterBackend()) { SendMythSystemEvent("MASTER_SHUTDOWN"); qApp->processEvents(); } gCoreContext->LogEntry("mythbackend", LP_INFO, "MythBackend exiting", ""); delete sysEventHandler; delete mainServer; return exitCode; }
int run_backend(MythBackendCommandLineParser &cmdline) { bool ismaster = gCoreContext->IsMasterHost(); if (!UpgradeTVDatabaseSchema(ismaster, ismaster)) { LOG(VB_GENERAL, LOG_ERR, "Couldn't upgrade database to new schema"); return GENERIC_EXIT_DB_OUTOFDATE; } MythTranslation::load("mythfrontend"); if (!ismaster) { int ret = connect_to_master(); if (ret != GENERIC_EXIT_OK) return ret; } QString myip = gCoreContext->GetSetting("BackendServerIP"); int port = gCoreContext->GetNumSetting("BackendServerPort", 6543); if (myip.isEmpty()) { cerr << "No setting found for this machine's BackendServerIP.\n" << "Please run setup on this machine and modify the first page\n" << "of the general settings.\n"; return GENERIC_EXIT_SETUP_ERROR; } MythSystemEventHandler *sysEventHandler = new MythSystemEventHandler(); if (ismaster) { LOG(VB_GENERAL, LOG_NOTICE, LOC + "Starting up as the master server."); } else { LOG(VB_GENERAL, LOG_NOTICE, LOC + "Running as a slave backend."); } print_warnings(cmdline); bool fatal_error = false; bool runsched = setupTVs(ismaster, fatal_error); if (fatal_error) { delete sysEventHandler; return GENERIC_EXIT_SETUP_ERROR; } if (ismaster) { if (runsched) { sched = new Scheduler(true, &tvList); int err = sched->GetError(); if (err) return err; if (cmdline.toBool("nosched")) sched->DisableScheduling(); } if (!cmdline.toBool("nohousekeeper")) housekeeping = new HouseKeeper(true, ismaster, sched); if (!cmdline.toBool("noautoexpire")) { expirer = new AutoExpire(&tvList); if (sched) sched->SetExpirer(expirer); } } else if (!cmdline.toBool("nohousekeeper")) { housekeeping = new HouseKeeper(true, ismaster, NULL); } if (!cmdline.toBool("nojobqueue")) jobqueue = new JobQueue(ismaster); // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- if (g_pUPnp == NULL) { g_pUPnp = new MediaServer(); g_pUPnp->Init(ismaster, cmdline.toBool("noupnp")); } // ---------------------------------------------------------------------- // Setup status server // ---------------------------------------------------------------------- HttpStatus *httpStatus = NULL; HttpServer *pHS = g_pUPnp->GetHttpServer(); if (pHS) { LOG(VB_GENERAL, LOG_INFO, "Main::Registering HttpStatus Extension"); httpStatus = new HttpStatus( &tvList, sched, expirer, ismaster ); pHS->RegisterExtension( httpStatus ); } MainServer *mainServer = new MainServer(ismaster, port, &tvList, sched, expirer); int exitCode = mainServer->GetExitCode(); if (exitCode != GENERIC_EXIT_OK) { LOG(VB_GENERAL, LOG_CRIT, "Backend exiting, MainServer initialization error."); delete mainServer; return exitCode; } if (httpStatus && mainServer) httpStatus->SetMainServer(mainServer); StorageGroup::CheckAllStorageGroupDirs(); if (gCoreContext->IsMasterBackend()) SendMythSystemEvent("MASTER_STARTED"); /////////////////////////////// /////////////////////////////// exitCode = qApp->exec(); /////////////////////////////// /////////////////////////////// if (gCoreContext->IsMasterBackend()) { SendMythSystemEvent("MASTER_SHUTDOWN"); qApp->processEvents(); } LOG(VB_GENERAL, LOG_NOTICE, "MythBackend exiting"); delete sysEventHandler; delete mainServer; cleanup(); return exitCode; }
int run_backend(MythBackendCommandLineParser &cmdline) { gBackendContext = new BackendContext(); if (!DBUtil::CheckTimeZoneSupport()) { LOG(VB_GENERAL, LOG_ERR, "MySQL time zone support is missing. " "Please install it and try again. " "See 'mysql_tzinfo_to_sql' for assistance."); return GENERIC_EXIT_DB_NOTIMEZONE; } bool ismaster = gCoreContext->IsMasterHost(); if (!UpgradeTVDatabaseSchema(ismaster, ismaster)) { LOG(VB_GENERAL, LOG_ERR, "Couldn't upgrade database to new schema"); return GENERIC_EXIT_DB_OUTOFDATE; } MythTranslation::load("mythfrontend"); if (!ismaster) { int ret = connect_to_master(); if (ret != GENERIC_EXIT_OK) return ret; } int port = gCoreContext->GetBackendServerPort(); if (gCoreContext->GetBackendServerIP().isEmpty()) { cerr << "No setting found for this machine's BackendServerIP.\n" << "Please run setup on this machine and modify the first page\n" << "of the general settings.\n"; return GENERIC_EXIT_SETUP_ERROR; } MythSystemEventHandler *sysEventHandler = new MythSystemEventHandler(); if (ismaster) { LOG(VB_GENERAL, LOG_NOTICE, LOC + "Starting up as the master server."); } else { LOG(VB_GENERAL, LOG_NOTICE, LOC + "Running as a slave backend."); } print_warnings(cmdline); bool fatal_error = false; bool runsched = setupTVs(ismaster, fatal_error); if (fatal_error) { delete sysEventHandler; return GENERIC_EXIT_SETUP_ERROR; } Scheduler *sched = NULL; if (ismaster) { if (runsched) { sched = new Scheduler(true, &tvList); int err = sched->GetError(); if (err) return err; if (cmdline.toBool("nosched")) sched->DisableScheduling(); } if (!cmdline.toBool("noautoexpire")) { expirer = new AutoExpire(&tvList); if (sched) sched->SetExpirer(expirer); } gCoreContext->SetScheduler(sched); } if (!cmdline.toBool("nohousekeeper")) { housekeeping = new HouseKeeper(); if (ismaster) { housekeeping->RegisterTask(new LogCleanerTask()); housekeeping->RegisterTask(new CleanupTask()); housekeeping->RegisterTask(new ThemeUpdateTask()); housekeeping->RegisterTask(new ArtworkTask()); housekeeping->RegisterTask(new MythFillDatabaseTask()); // only run this task if MythMusic is installed and we have a new enough schema if (gCoreContext->GetNumSetting("MusicDBSchemaVer", 0) >= 1024) housekeeping->RegisterTask(new RadioStreamUpdateTask()); } housekeeping->RegisterTask(new JobQueueRecoverTask()); #ifdef __linux__ #ifdef CONFIG_BINDINGS_PYTHON housekeeping->RegisterTask(new HardwareProfileTask()); #endif #endif housekeeping->Start(); } if (!cmdline.toBool("nojobqueue")) jobqueue = new JobQueue(ismaster); // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- if (g_pUPnp == NULL) { g_pUPnp = new MediaServer(); g_pUPnp->Init(ismaster, cmdline.toBool("noupnp")); } // ---------------------------------------------------------------------- // Setup status server // ---------------------------------------------------------------------- HttpStatus *httpStatus = NULL; HttpServer *pHS = g_pUPnp->GetHttpServer(); if (pHS) { LOG(VB_GENERAL, LOG_INFO, "Main::Registering HttpStatus Extension"); httpStatus = new HttpStatus( &tvList, sched, expirer, ismaster ); pHS->RegisterExtension( httpStatus ); } mainServer = new MainServer( ismaster, port, &tvList, sched, expirer); int exitCode = mainServer->GetExitCode(); if (exitCode != GENERIC_EXIT_OK) { LOG(VB_GENERAL, LOG_CRIT, "Backend exiting, MainServer initialization error."); cleanup(); return exitCode; } if (httpStatus && mainServer) httpStatus->SetMainServer(mainServer); StorageGroup::CheckAllStorageGroupDirs(); if (gCoreContext->IsMasterBackend()) gCoreContext->SendSystemEvent("MASTER_STARTED"); #ifdef USING_SYSTEMD_NOTIFY // Provide systemd ready notification (for type=notify units) (void)sd_notify(0, "READY=1"); #endif /////////////////////////////// /////////////////////////////// exitCode = qApp->exec(); /////////////////////////////// /////////////////////////////// if (gCoreContext->IsMasterBackend()) { gCoreContext->SendSystemEvent("MASTER_SHUTDOWN"); qApp->processEvents(); } LOG(VB_GENERAL, LOG_NOTICE, "MythBackend exiting"); delete sysEventHandler; return exitCode; }
int main(int argc, char **argv) { bool need_gui = false; #ifndef _WIN32 for (int i = 3; i < sysconf(_SC_OPEN_MAX) - 1; ++i) close(i); #else // MINGW application needs a window to receive messages // such as socket notifications :[ need_gui = true; #endif QApplication a(argc, argv, need_gui); QMap<QString, QString> settingsOverride; QString binname = basename(a.argv()[0]); long long previewFrameNumber = -2; long long previewSeconds = -2; QSize previewSize(0,0); QString chanid = QString::null; QString starttime = QString::null; QString infile = QString::null; QString outfile = QString::null; bool daemonize = false; bool printsched = false; bool testsched = false; bool resched = false; bool nosched = false; bool noupnp = false; bool nojobqueue = false; bool nohousekeeper = false; bool noexpirer = false; QString printexpire = ""; bool clearsettingscache = false; bool wantupnprebuild = false; for (int argpos = 1; argpos < a.argc(); ++argpos) { if (!strcmp(a.argv()[argpos],"-l") || !strcmp(a.argv()[argpos],"--logfile")) { if (a.argc() > argpos) { logfile = a.argv()[argpos+1]; if (logfile.startsWith("-")) { cerr << "Invalid or missing argument to -l/--logfile option\n"; return BACKEND_EXIT_INVALID_CMDLINE; } else { ++argpos; } } } else if (!strcmp(a.argv()[argpos],"-p") || !strcmp(a.argv()[argpos],"--pidfile")) { if (a.argc() > argpos) { pidfile = a.argv()[argpos+1]; if (pidfile.startsWith("-")) { cerr << "Invalid or missing argument to -p/--pidfile option\n"; return BACKEND_EXIT_INVALID_CMDLINE; } else { ++argpos; } } } else if (!strcmp(a.argv()[argpos],"-d") || !strcmp(a.argv()[argpos],"--daemon")) { daemonize = true; } else if (!strcmp(a.argv()[argpos],"-O") || !strcmp(a.argv()[argpos],"--override-setting")) { if (a.argc()-1 > argpos) { QString tmpArg = a.argv()[argpos+1]; if (tmpArg.startsWith("-")) { cerr << "Invalid or missing argument to -O/--override-setting option\n"; return BACKEND_EXIT_INVALID_CMDLINE; } QStringList pairs = QStringList::split(",", tmpArg); for (unsigned int index = 0; index < pairs.size(); ++index) { QStringList tokens = QStringList::split("=", pairs[index]); tokens[0].replace(QRegExp("^[\"']"), ""); tokens[0].replace(QRegExp("[\"']$"), ""); tokens[1].replace(QRegExp("^[\"']"), ""); tokens[1].replace(QRegExp("[\"']$"), ""); settingsOverride[tokens[0]] = tokens[1]; } } else { cerr << "Invalid or missing argument to -O/--override-setting option\n"; return BACKEND_EXIT_INVALID_CMDLINE; } ++argpos; } else if (!strcmp(a.argv()[argpos],"-v") || !strcmp(a.argv()[argpos],"--verbose")) { if (a.argc()-1 > argpos) { if (parse_verbose_arg(a.argv()[argpos+1]) == GENERIC_EXIT_INVALID_CMDLINE) return BACKEND_EXIT_INVALID_CMDLINE; ++argpos; } else { cerr << "Missing argument to -v/--verbose option\n"; return BACKEND_EXIT_INVALID_CMDLINE; } } else if (!strcmp(a.argv()[argpos],"--printsched")) { printsched = true; } else if (!strcmp(a.argv()[argpos],"--testsched")) { testsched = true; } else if (!strcmp(a.argv()[argpos],"--resched")) { resched = true; } else if (!strcmp(a.argv()[argpos],"--nosched")) { nosched = true; } else if (!strcmp(a.argv()[argpos],"--noupnp")) { noupnp = true; } else if (!strcmp(a.argv()[argpos],"--upnprebuild")) { wantupnprebuild = true; } else if (!strcmp(a.argv()[argpos],"--nojobqueue")) { nojobqueue = true; } else if (!strcmp(a.argv()[argpos],"--nohousekeeper")) { nohousekeeper = true; } else if (!strcmp(a.argv()[argpos],"--noautoexpire")) { noexpirer = true; } else if (!strcmp(a.argv()[argpos],"--printexpire")) { printexpire = "ALL"; if ((a.argc()-1 > argpos) && a.argv()[argpos+1][0] != '-') { printexpire = a.argv()[argpos+1]; ++argpos; } } else if (!strcmp(a.argv()[argpos],"--clearcache")) { clearsettingscache = true; } else if (!strcmp(a.argv()[argpos],"--version")) { extern const char *myth_source_version; extern const char *myth_source_path; cout << "Please include all output in bug reports." << endl; cout << "MythTV Version : " << myth_source_version << endl; cout << "MythTV Branch : " << myth_source_path << endl; cout << "Library API : " << MYTH_BINARY_VERSION << endl; cout << "Network Protocol : " << MYTH_PROTO_VERSION << endl; #ifdef MYTH_BUILD_CONFIG cout << "Options compiled in:" <<endl; cout << MYTH_BUILD_CONFIG << endl; #endif return BACKEND_EXIT_OK; } else if (!strcmp(a.argv()[argpos],"--generate-preview")) { QString tmp = QString::null; if ((argpos + 1) < a.argc()) { tmp = a.argv()[argpos+1]; bool ok = true; if (tmp.left(1) == "-") tmp.left(2).toInt(&ok); if (ok) argpos++; else tmp = QString::null; } if (!parse_preview_info(tmp, previewFrameNumber, previewSeconds, previewSize)) { VERBOSE(VB_IMPORTANT, QString("Unable to parse --generate-preview " "option '%1'").arg(tmp)); return BACKEND_EXIT_INVALID_CMDLINE; } } else if (!strcmp(a.argv()[argpos],"-c") || !strcmp(a.argv()[argpos],"--chanid")) { if (((argpos + 1) >= a.argc()) || !strncmp(a.argv()[argpos + 1], "-", 1)) { VERBOSE(VB_IMPORTANT, "Missing or invalid parameters for --chanid option"); return BACKEND_EXIT_INVALID_CMDLINE; } chanid = a.argv()[++argpos]; } else if (!strcmp(a.argv()[argpos],"-s") || !strcmp(a.argv()[argpos],"--starttime")) { if (((argpos + 1) >= a.argc()) || !strncmp(a.argv()[argpos + 1], "-", 1)) { VERBOSE(VB_IMPORTANT, "Missing or invalid parameters for --starttime option"); return BACKEND_EXIT_INVALID_CMDLINE; } starttime = a.argv()[++argpos]; } else if (!strcmp(a.argv()[argpos],"--infile")) { if (((argpos + 1) >= a.argc()) || !strncmp(a.argv()[argpos + 1], "-", 1)) { VERBOSE(VB_IMPORTANT, "Missing or invalid parameters for --infile option"); return BACKEND_EXIT_INVALID_CMDLINE; } infile = a.argv()[++argpos]; } else if (!strcmp(a.argv()[argpos],"--outfile")) { if (((argpos + 1) >= a.argc()) || !strncmp(a.argv()[argpos + 1], "-", 1)) { VERBOSE(VB_IMPORTANT, "Missing or invalid parameters for --outfile option"); return BACKEND_EXIT_INVALID_CMDLINE; } outfile = a.argv()[++argpos]; } else { if (!(!strcmp(a.argv()[argpos],"-h") || !strcmp(a.argv()[argpos],"--help"))) cerr << "Invalid argument: " << a.argv()[argpos] << endl; cerr << "Valid options are: " << endl << "-h or --help List valid command line parameters" << endl << "-l or --logfile filename Writes STDERR and STDOUT messages to filename" << endl << "-p or --pidfile filename Write PID of mythbackend " << "to filename" << endl << "-d or --daemon Runs mythbackend as a daemon" << endl << "-v or --verbose debug-level Use '-v help' for level info" << endl << "--printexpire List of auto-expire programs" << endl << "--printsched Upcoming scheduled programs" << endl << "--testsched Test run scheduler (ignore existing schedule)" << endl << "--resched Force the scheduler to update" << endl << "--nosched Do not perform any scheduling" << endl << "--noupnp Do not enable the UPNP server" << endl << "--nojobqueue Do not start the JobQueue" << endl << "--nohousekeeper Do not start the Housekeeper" << endl << "--noautoexpire Do not start the AutoExpire thread" << endl << "--clearcache Clear the settings cache on all myth servers" << endl << "--version Version information" << endl << "--generate-preview Generate a preview image" << endl << "--upnprebuild Force an update of UPNP media" << endl << "--infile Input file for preview generation" << endl << "--outfile Optional output file for preview generation" << endl << "--chanid Channel ID for preview generation" << endl << "--starttime Recording start time for preview generation" << endl; return BACKEND_EXIT_INVALID_CMDLINE; } } if (((previewFrameNumber >= -1) || previewSeconds >= -1) && (chanid.isEmpty() || starttime.isEmpty()) && infile.isEmpty()) { cerr << "--generate-preview must be accompanied by either " <<endl << "\nboth --chanid and --starttime paramaters, " << endl << "\nor the --infile paramater." << endl; return BACKEND_EXIT_INVALID_CMDLINE; } if (logfile != "" ) { if (log_rotate(1) < 0) cerr << "cannot open logfile; using stdout/stderr" << endl; else signal(SIGHUP, &log_rotate_handler); } ofstream pidfs; if (pidfile != "") { pidfs.open(pidfile.ascii()); if (!pidfs) { perror(pidfile.ascii()); cerr << "Error opening pidfile"; return BACKEND_EXIT_OPENING_PIDFILE_ERROR; } } if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) cerr << "Unable to ignore SIGPIPE\n"; if (daemonize) if (daemon(0, 1) < 0) { perror("daemon"); return BACKEND_EXIT_DAEMONIZING_ERROR; } if (pidfs) { pidfs << getpid() << endl; pidfs.close(); } gContext = NULL; gContext = new MythContext(MYTH_BINARY_VERSION); if (!gContext->Init(false)) { VERBOSE(VB_IMPORTANT, "Failed to init MythContext, exiting."); return BACKEND_EXIT_NO_MYTHCONTEXT; } gContext->SetBackend(true); if (wantupnprebuild) { VERBOSE(VB_GENERAL, "Rebuilding UPNP Media Map"); UPnpMedia *rebuildit = new UPnpMedia(false,false); rebuildit->BuildMediaMap(); return BACKEND_EXIT_OK; } if (clearsettingscache) { if (gContext->ConnectToMasterServer()) { RemoteSendMessage("CLEAR_SETTINGS_CACHE"); VERBOSE(VB_IMPORTANT, "Sent CLEAR_SETTINGS_CACHE message"); return BACKEND_EXIT_OK; } else { VERBOSE(VB_IMPORTANT, "Unable to connect to backend, settings " "cache will not be cleared."); return BACKEND_EXIT_NO_CONNECT; } } if (settingsOverride.size()) { QMap<QString, QString>::iterator it; for (it = settingsOverride.begin(); it != settingsOverride.end(); ++it) { VERBOSE(VB_IMPORTANT, QString("Setting '%1' being forced to '%2'") .arg(it.key()).arg(it.data())); gContext->OverrideSettingForSession(it.key(), it.data()); } } gContext->ActivateSettingsCache(false); if ((CompareTVDatabaseSchemaVersion() > 0) && // and Not MythContext::PromptForSchemaUpgrade() expertMode (gContext->GetNumSetting("DBSchemaAutoUpgrade") != -1)) { VERBOSE(VB_IMPORTANT, "The schema version of your existing database " "is newer than this version of MythTV understands. Please " "ensure that you have selected the proper database server or " "upgrade this and all other frontends and backends to the " "same MythTV version and revision."); return BACKEND_EXIT_DB_OUTOFDATE; } if (!UpgradeTVDatabaseSchema()) { VERBOSE(VB_IMPORTANT, "Couldn't upgrade database to new schema"); return BACKEND_EXIT_DB_OUTOFDATE; } gContext->ActivateSettingsCache(true); close(0); if (printsched || testsched) { gContext->SetBackend(false); sched = new Scheduler(false, &tvList); if (!testsched && gContext->ConnectToMasterServer()) { cout << "Retrieving Schedule from Master backend.\n"; sched->FillRecordListFromMaster(); } else { cout << "Calculating Schedule from database.\n" << "Inputs, Card IDs, and Conflict info may be invalid " "if you have multiple tuners.\n"; sched->FillRecordListFromDB(); } print_verbose_messages |= VB_SCHEDULE; sched->PrintList(true); cleanup(); return BACKEND_EXIT_OK; } if (resched) { gContext->SetBackend(false); bool ok = false; if (gContext->ConnectToMasterServer()) { VERBOSE(VB_IMPORTANT, "Connected to master for reschedule"); ScheduledRecording::signalChange(-1); ok = true; } else VERBOSE(VB_IMPORTANT, "Cannot connect to master for reschedule"); cleanup(); return (ok) ? BACKEND_EXIT_OK : BACKEND_EXIT_NO_CONNECT; } if (printexpire != "") { expirer = new AutoExpire(); expirer->PrintExpireList(printexpire); cleanup(); return BACKEND_EXIT_OK; } if ((previewFrameNumber >= -1) || (previewSeconds >= -1)) { return preview_helper( chanid, starttime, previewFrameNumber, previewSeconds, previewSize, infile, outfile); } int port = gContext->GetNumSetting("BackendServerPort", 6543); QString myip = gContext->GetSetting("BackendServerIP"); if (myip.isNull() || myip.isEmpty()) { cerr << "No setting found for this machine's BackendServerIP.\n" << "Please run setup on this machine and modify the first page\n" << "of the general settings.\n"; return BACKEND_EXIT_NO_IP_ADDRESS; } bool ismaster = gContext->IsMasterHost(); if (ismaster) { cerr << "Starting up as the master server.\n"; gContext->LogEntry("mythbackend", LP_INFO, "MythBackend started as master server", ""); if (nosched) cerr << "********** The Scheduler has been DISABLED with " "the --nosched option **********\n"; // kill -USR1 mythbackendpid will force a upnpmedia rebuild signal(SIGUSR1, &upnp_rebuild); } else { cerr << "Running as a slave backend.\n"; gContext->LogEntry("mythbackend", LP_INFO, "MythBackend started as a slave backend", ""); } // Get any initial housekeeping done before we fire up anything else if (nohousekeeper) cerr << "****** The Housekeeper has been DISABLED with " "the --nohousekeeper option ******\n"; else housekeeping = new HouseKeeper(true, ismaster); bool fatal_error = false; bool runsched = setupTVs(ismaster, fatal_error); if (fatal_error) return BACKEND_EXIT_CAP_CARD_SETUP_ERROR; if (ismaster && runsched) { sched = new Scheduler(true, &tvList); if (nosched) sched->DisableScheduling(); } if (ismaster) { if (noexpirer) cerr << "********* Auto-Expire has been DISABLED with " "the --noautoexpire option ********\n"; else expirer = new AutoExpire(&tvList); } if (sched && expirer) sched->SetExpirer(expirer); if (nojobqueue) cerr << "********* The JobQueue has been DISABLED with " "the --nojobqueue option *********\n"; else jobqueue = new JobQueue(ismaster); // Start UPnP Services g_pUPnp = new MediaServer( ismaster, noupnp ); HttpServer *pHS = g_pUPnp->GetHttpServer(); if (pHS) { VERBOSE(VB_IMPORTANT, "Main::Registering HttpStatus Extension"); pHS->RegisterExtension( new HttpStatus( &tvList, sched, expirer, ismaster )); } VERBOSE(VB_IMPORTANT, QString("%1 version: %2 www.mythtv.org") .arg(binname).arg(MYTH_BINARY_VERSION)); VERBOSE(VB_IMPORTANT, QString("Enabled verbose msgs: %1").arg(verboseString)); new MainServer(ismaster, port, &tvList, sched, expirer); if (ismaster) { QString WOLslaveBackends = gContext->GetSetting("WOLslaveBackendsCommand",""); if (!WOLslaveBackends.isEmpty()) { VERBOSE(VB_IMPORTANT, "Waking slave Backends now."); system(WOLslaveBackends.ascii()); } } StorageGroup::CheckAllStorageGroupDirs(); a.exec(); gContext->LogEntry("mythbackend", LP_INFO, "MythBackend exiting", ""); cleanup(); return BACKEND_EXIT_OK; }