Source* Station::getSourceByName() { std::string path(Core::AbstractConfig::prefix); path += Core::AbstractConfig::sourcesPath; SourceList *sourcelist = new Core::SourceList(path); for (int i=0; i<(int)sourcelist->size(); i++){ if (_sourceName->compare(sourcelist->at(i)->name()) == 0){ Source* source = new Core::Source(*sourcelist->at(i)); delete sourcelist; return source; } } return 0; }
void build_sources_and_dests(const size_t num_sources_x, const size_t num_sources_y, const size_t num_dests_x, const size_t num_dests_y, const size_t ts_size, const shyft::timeseries::utctimespan dt, const point_timeaxis& time_axis, bool insert_nans, SourceList& sources, DestinationList& dests,bool randomize=false) { const double x_min = 0.0; // [m] const double x_max = 100000.0; // [m] const double y_min = 0.0; // [m] const double y_max = 1000000.0; // [m] sources.reserve(num_sources_x*num_sources_y); dests.reserve(num_dests_x*num_dests_y); geo_point pt; double lower_bound = 0.0; double upper_bound = 10.0; std::uniform_real_distribution<double> unif(lower_bound, upper_bound); std::default_random_engine re; vector<utctime> times;times.reserve(ts_size); for (size_t l = 0; l < ts_size; ++l) times.emplace_back(l*dt); times.emplace_back(shyft::core::max_utctime); point_timeaxis dta(times); geo_point p0(x_min,y_min,0.0); const double max_distance=geo_point::xy_distance(p0,geo_point(x_max,y_max,0.0)); auto base_temp=[&unif,&re,randomize,&p0,max_distance](geo_point p1)->double { if(randomize) return unif(re); return 10+ 2.0*geo_point::xy_distance(p0,p1)/max_distance; }; for (size_t i = 0; i < num_sources_x; ++i) { pt.x = x_min + i*(x_max - x_min) / (num_sources_x - 1); for (size_t j = 0; j < num_sources_y; ++j) { pt.y = y_min + j*(y_max - y_min) / (num_sources_y - 1); pt.z = 500 * std::sin(pt.x / x_max) + std::sin(pt.y / y_max) / 2; vector<double> pts; pts.reserve(ts_size); double b_t = base_temp(pt); for (size_t l = 0; l < ts_size; ++l) pts.emplace_back( b_t + pt.z*(0.6 / 100)); sources.emplace_back(pt, xpts_t(dta,pts)); } } for (size_t i = 0; i < num_dests_x; ++i) { pt.x = x_min + i*(x_max - x_min) / (num_dests_x - 1); for (size_t j = 0; j < num_dests_y; ++j) { pt.y = y_min + j*(y_max - y_min) / (num_dests_y - 1); pt.z = 500 * (std::sin(pt.x / x_max) + std::sin(pt.y / y_max)) / 2; dests.emplace_back(pt, time_axis); } } }
// Clear all sources from the monitored sources list void XmlRpcDispatch::clear() { if (_inWork) { _doClear = true; // Finish reporting current events before clearing } else { SourceList sourcesToClose; _sources.swap(sourcesToClose); for (SourceList::iterator it=sourcesToClose.begin(); it!=sourcesToClose.end(); ++it) it->getSource()->close(); } }
void build_sources_and_dests(const size_t num_sources_x, const size_t num_sources_y, const size_t num_dests_x, const size_t num_dests_y, const size_t ts_size, const shyft::timeseries::utctimespan dt, const point_timeaxis& time_axis, bool insert_nans, SourceList& sources, DestinationList& dests) { const double x_min = 0.0; // [m] const double x_max = 100000.0; // [m] const double y_min = 0.0; // [m] const double y_max = 1000000.0; // [m] sources.reserve(num_sources_x*num_sources_y); dests.reserve(num_dests_x*num_dests_y); geo_point pt; double lower_bound = 0.0; double upper_bound = 10.0; std::uniform_real_distribution<double> unif(lower_bound, upper_bound); std::default_random_engine re; vector<utctime> times;times.reserve(ts_size); for (size_t l = 0; l < ts_size; ++l) times.emplace_back(l*dt); times.emplace_back(shyft::core::max_utctime); point_timeaxis dta(times); for (size_t i = 0; i < num_sources_x; ++i) { pt.x = x_min + i*(x_max - x_min) / (num_sources_x - 1); for (size_t j = 0; j < num_sources_y; ++j) { pt.y = y_min + j*(y_max - y_min) / (num_sources_y - 1); pt.z = 500 * std::sin(pt.x / x_max) + std::sin(pt.y / y_max) / 2; vector<double> pts; pts.reserve(ts_size); double b_t = unif(re); //std::cout << "Base temp at pos (i,j) = " << i << ", " << j << ") = " << b_t << std::endl; for (size_t l = 0; l < ts_size; ++l) pts.emplace_back( b_t + pt.z*(0.6 / 100)); sources.emplace_back(pt, xpts_t(dta,pts)); } } for (size_t i = 0; i < num_dests_x; ++i) { pt.x = x_min + i*(x_max - x_min) / (num_dests_x - 1); for (size_t j = 0; j < num_dests_y; ++j) { pt.y = y_min + j*(y_max - y_min) / (num_dests_y - 1); pt.z = 500 * (std::sin(pt.x / x_max) + std::sin(pt.y / y_max)) / 2; dests.emplace_back(pt, time_axis); } } }
/** \fn FillData::Run(SourceList &sourcelist) * \brief Goes through the sourcelist and updates its channels with * program info grabbed with the associated grabber. * \return true if there were no failures */ bool FillData::Run(SourceList &sourcelist) { SourceList::iterator it; SourceList::iterator it2; QString status, querystr; MSqlQuery query(MSqlQuery::InitCon()); QDateTime GuideDataBefore, GuideDataAfter; int failures = 0; int externally_handled = 0; int total_sources = sourcelist.size(); int source_channels = 0; QString sidStr = QString("Updating source #%1 (%2) with grabber %3"); need_post_grab_proc = false; int nonewdata = 0; bool has_dd_source = false; // find all DataDirect duplicates, so we only data download once. for (it = sourcelist.begin(); it != sourcelist.end(); ++it) { if (!is_grabber_datadirect((*it).xmltvgrabber)) continue; has_dd_source = true; for (it2 = sourcelist.begin(); it2 != sourcelist.end(); ++it2) { if (((*it).id != (*it2).id) && ((*it).xmltvgrabber == (*it2).xmltvgrabber) && ((*it).userid == (*it2).userid) && ((*it).password == (*it2).password)) { (*it).dd_dups.push_back((*it2).id); } } } if (has_dd_source) ddprocessor.CreateTempDirectory(); for (it = sourcelist.begin(); it != sourcelist.end(); ++it) { if (!fatalErrors.empty()) break; query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c " "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID " "AND manualid = 0;"); query.bindValue(":SRCID", (*it).id); if (query.exec() && query.size() > 0) { query.next(); if (!query.isNull(0)) GuideDataBefore = QDateTime::fromString(query.value(0).toString(), Qt::ISODate); } channel_update_run = false; endofdata = false; QString xmltv_grabber = (*it).xmltvgrabber; if (xmltv_grabber == "eitonly") { LOG(VB_GENERAL, LOG_INFO, QString("Source %1 configured to use only the " "broadcasted guide data. Skipping.") .arg((*it).id)); externally_handled++; updateLastRunStart(query); updateLastRunEnd(query); continue; } else if (xmltv_grabber.trimmed().isEmpty() || xmltv_grabber == "/bin/true" || xmltv_grabber == "none") { LOG(VB_GENERAL, LOG_INFO, QString("Source %1 configured with no grabber. Nothing to do.") .arg((*it).id)); externally_handled++; updateLastRunStart(query); updateLastRunEnd(query); continue; } LOG(VB_GENERAL, LOG_INFO, sidStr.arg((*it).id) .arg((*it).name) .arg(xmltv_grabber)); query.prepare( "SELECT COUNT(chanid) FROM channel WHERE sourceid = " ":SRCID AND xmltvid != ''"); query.bindValue(":SRCID", (*it).id); if (query.exec() && query.size() > 0) { query.next(); source_channels = query.value(0).toInt(); if (source_channels > 0) { LOG(VB_GENERAL, LOG_INFO, QString("Found %1 channels for source %2 which use grabber") .arg(source_channels).arg((*it).id)); } else { LOG(VB_GENERAL, LOG_INFO, QString("No channels are configured to use grabber.")); } } else { source_channels = 0; LOG(VB_GENERAL, LOG_INFO, QString("Can't get a channel count for source id %1") .arg((*it).id)); } bool hasprefmethod = false; if (is_grabber_external(xmltv_grabber)) { uint flags = kMSRunShell | kMSStdOut | kMSBuffered; MythSystem grabber_capabilities_proc(xmltv_grabber, QStringList("--capabilities"), flags); grabber_capabilities_proc.Run(25); if (grabber_capabilities_proc.Wait() != GENERIC_EXIT_OK) LOG(VB_GENERAL, LOG_ERR, QString("%1 --capabilities failed or we timed out waiting." " You may need to upgrade your xmltv grabber") .arg(xmltv_grabber)); else { QByteArray result = grabber_capabilities_proc.ReadAll(); QTextStream ostream(result); QString capabilities; while (!ostream.atEnd()) { QString capability = ostream.readLine().simplified(); if (capability.isEmpty()) continue; capabilities += capability + ' '; if (capability == "baseline") (*it).xmltvgrabber_baseline = true; if (capability == "manualconfig") (*it).xmltvgrabber_manualconfig = true; if (capability == "cache") (*it).xmltvgrabber_cache = true; if (capability == "preferredmethod") hasprefmethod = true; } LOG(VB_GENERAL, LOG_INFO, QString("Grabber has capabilities: %1") .arg(capabilities)); } } if (hasprefmethod) { uint flags = kMSRunShell | kMSStdOut | kMSBuffered; MythSystem grabber_method_proc(xmltv_grabber, QStringList("--preferredmethod"), flags); grabber_method_proc.Run(15); if (grabber_method_proc.Wait() != GENERIC_EXIT_OK) LOG(VB_GENERAL, LOG_ERR, QString("%1 --preferredmethod failed or we timed out " "waiting. You may need to upgrade your xmltv " "grabber").arg(xmltv_grabber)); else { QTextStream ostream(grabber_method_proc.ReadAll()); (*it).xmltvgrabber_prefmethod = ostream.readLine().simplified(); LOG(VB_GENERAL, LOG_INFO, QString("Grabber prefers method: %1") .arg((*it).xmltvgrabber_prefmethod)); } } need_post_grab_proc |= !is_grabber_datadirect(xmltv_grabber); if (is_grabber_datadirect(xmltv_grabber) && dd_grab_all) { if (only_update_channels) DataDirectUpdateChannels(*it); else { QDate qCurrentDate = QDate::currentDate(); if (!GrabData(*it, 0, &qCurrentDate)) ++failures; } } else if ((*it).xmltvgrabber_prefmethod == "allatonce") { if (!GrabData(*it, 0)) ++failures; } else if ((*it).xmltvgrabber_baseline || is_grabber_datadirect(xmltv_grabber)) { QDate qCurrentDate = QDate::currentDate(); // We'll keep grabbing until it returns nothing // Max days currently supported is 21 int grabdays = (is_grabber_datadirect(xmltv_grabber)) ? 14 : REFRESH_MAX; grabdays = (maxDays > 0) ? maxDays : grabdays; grabdays = (only_update_channels) ? 1 : grabdays; vector<bool> refresh_request; refresh_request.resize(grabdays, refresh_all); for (int i = 0; i < refresh_day.size(); i++) refresh_request[i] = refresh_day[i]; if (is_grabber_datadirect(xmltv_grabber) && only_update_channels) { DataDirectUpdateChannels(*it); grabdays = 0; } for (int i = 0; i < grabdays; i++) { if (!fatalErrors.empty()) break; // We need to check and see if the current date has changed // since we started in this loop. If it has, we need to adjust // the value of 'i' to compensate for this. if (QDate::currentDate() != qCurrentDate) { QDate newDate = QDate::currentDate(); i += (newDate.daysTo(qCurrentDate)); if (i < 0) i = 0; qCurrentDate = newDate; } QString prevDate(qCurrentDate.addDays(i-1).toString()); QString currDate(qCurrentDate.addDays(i).toString()); LOG(VB_GENERAL, LOG_INFO, ""); // add a space between days LOG(VB_GENERAL, LOG_INFO, "Checking day @ " + QString("offset %1, date: %2").arg(i).arg(currDate)); bool download_needed = false; if (refresh_request[i]) { if ( i == 1 ) { LOG(VB_GENERAL, LOG_INFO, "Data Refresh always needed for tomorrow"); } else { LOG(VB_GENERAL, LOG_INFO, "Data Refresh needed because of user request"); } download_needed = true; } else { // Check to see if we already downloaded data for this date. querystr = "SELECT c.chanid, COUNT(p.starttime) " "FROM channel c " "LEFT JOIN program p ON c.chanid = p.chanid " " AND starttime >= " "DATE_ADD(DATE_ADD(CURRENT_DATE(), " "INTERVAL '%1' DAY), INTERVAL '20' HOUR) " " AND starttime < DATE_ADD(CURRENT_DATE(), " "INTERVAL '%2' DAY) " "WHERE c.sourceid = %3 AND c.xmltvid != '' " "GROUP BY c.chanid;"; if (query.exec(querystr.arg(i-1).arg(i).arg((*it).id)) && query.isActive()) { int prevChanCount = 0; int currentChanCount = 0; int previousDayCount = 0; int currentDayCount = 0; LOG(VB_CHANNEL, LOG_INFO, QString("Checking program counts for day %1") .arg(i-1)); while (query.next()) { if (query.value(1).toInt() > 0) prevChanCount++; previousDayCount += query.value(1).toInt(); LOG(VB_CHANNEL, LOG_INFO, QString(" chanid %1 -> %2 programs") .arg(query.value(0).toString()) .arg(query.value(1).toInt())); } if (query.exec(querystr.arg(i).arg(i+1).arg((*it).id)) && query.isActive()) { LOG(VB_CHANNEL, LOG_INFO, QString("Checking program counts for day %1") .arg(i)); while (query.next()) { if (query.value(1).toInt() > 0) currentChanCount++; currentDayCount += query.value(1).toInt(); LOG(VB_CHANNEL, LOG_INFO, QString(" chanid %1 -> %2 programs") .arg(query.value(0).toString()) .arg(query.value(1).toInt())); } } else { LOG(VB_GENERAL, LOG_INFO, QString("Data Refresh because we are unable to " "query the data for day %1 to " "determine if we have enough").arg(i)); download_needed = true; } if (currentChanCount < (prevChanCount * 0.90)) { LOG(VB_GENERAL, LOG_INFO, QString("Data refresh needed because only %1 " "out of %2 channels have at least one " "program listed for day @ offset %3 " "from 8PM - midnight. Previous day " "had %4 channels with data in that " "time period.") .arg(currentChanCount).arg(source_channels) .arg(i).arg(prevChanCount)); download_needed = true; } else if (currentDayCount == 0) { LOG(VB_GENERAL, LOG_INFO, QString("Data refresh needed because no data " "exists for day @ offset %1 from 8PM - " "midnight.").arg(i)); download_needed = true; } else if (previousDayCount == 0) { LOG(VB_GENERAL, LOG_INFO, QString("Data refresh needed because no data " "exists for day @ offset %1 from 8PM - " "midnight. Unable to calculate how " "much we should have for the current " "day so a refresh is being forced.") .arg(i-1)); download_needed = true; } else if (currentDayCount < (currentChanCount * 3)) { LOG(VB_GENERAL, LOG_INFO, QString("Data Refresh needed because offset " "day %1 has less than 3 programs " "per channel for the 8PM - midnight " "time window for channels that " "normally have data. " "We want at least %2 programs, but " "only found %3") .arg(i).arg(currentChanCount * 3) .arg(currentDayCount)); download_needed = true; } else if (currentDayCount < (previousDayCount / 2)) { LOG(VB_GENERAL, LOG_INFO, QString("Data Refresh needed because offset " "day %1 has less than half the number " "of programs as the previous day for " "the 8PM - midnight time window. " "We want at least %2 programs, but " "only found %3").arg(i) .arg(previousDayCount / 2) .arg(currentDayCount)); download_needed = true; } } else { LOG(VB_GENERAL, LOG_INFO, QString("Data Refresh needed because we are unable " "to query the data for day @ offset %1 to " "determine how much we should have for " "offset day %2.").arg(i-1).arg(i)); download_needed = true; } } if (download_needed) { LOG(VB_GENERAL, LOG_NOTICE, QString("Refreshing data for ") + currDate); if (!GrabData(*it, i, &qCurrentDate)) { ++failures; if (!fatalErrors.empty() || interrupted) { break; } } if (endofdata) { LOG(VB_GENERAL, LOG_INFO, "Grabber is no longer returning program data, " "finishing"); break; } } else { LOG(VB_GENERAL, LOG_NOTICE, QString("Data is already present for ") + currDate + ", skipping"); } } if (!fatalErrors.empty()) break; } else { LOG(VB_GENERAL, LOG_ERR, QString("Grabbing XMLTV data using ") + xmltv_grabber + " is not supported. You may need to upgrade to" " the latest version of XMLTV."); } if (interrupted) { break; } query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c " "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID " "AND manualid = 0;"); query.bindValue(":SRCID", (*it).id); if (query.exec() && query.size() > 0) { query.next(); if (!query.isNull(0)) GuideDataAfter = QDateTime::fromString( query.value(0).toString(), Qt::ISODate); } if (GuideDataAfter == GuideDataBefore) { nonewdata++; } } if (!fatalErrors.empty()) { for (int i = 0; i < fatalErrors.size(); i++) { LOG(VB_GENERAL, LOG_CRIT, LOC + "Encountered Fatal Error: " + fatalErrors[i]); } return false; } if (only_update_channels && !need_post_grab_proc) return true; if (failures == 0) { if (nonewdata > 0 && (total_sources != externally_handled)) status = QString(QObject::tr( "mythfilldatabase ran, but did not insert " "any new data into the Guide for %1 of %2 sources. " "This can indicate a potential grabber failure.")) .arg(nonewdata) .arg(total_sources); else status = QObject::tr("Successful."); updateLastRunStatus(query, status); } return (failures == 0); }
// Watch current set of sources and process events void XmlRpcDispatch::work(double timeout_ms, XmlRpcClient *chunkWait) { // Compute end time _endTime = (timeout_ms < 0.0) ? -1.0 : (getTime() + timeout_ms/1000.0); _doClear = false; _inWork = true; if (chunkWait) { setSourceEvents(chunkWait, ReadableEvent | WritableEvent | Exception); } // Only work while there is something to monitor while (_sources.size() > 0) { // Construct the sets of descriptors we are interested in struct pollfd fds[MAX_POLLS]; nfds_t nfds = 0; addToFds (fds, nfds); fds[nfds].fd = -1; // Check for events int nEvents; if (timeout_ms < 0.0) nEvents = poll(fds, nfds, 0); else { struct timespec tv; tv.tv_sec = (int) floor (timeout_ms / 1000.0); tv.tv_nsec = (int) (fmod (timeout_ms, 1000.0) * 1000000.0); nEvents = ppoll(fds, nfds, &tv, NULL); } if (nEvents < 0) { XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents); _inWork = false; return; } checkFds (fds, nfds, chunkWait); // Check whether to clear all sources if (_doClear) { SourceList closeList = _sources; _sources.clear(); for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) { XmlRpcSource *src = it->getSource(); src->close(); } _doClear = false; } // Check whether end time has passed if (0 <= _endTime && getTime() > _endTime) break; // if chunkWait and the connection received chunk.. if (chunkWait && chunkWait->gotChunk ()) break; } _inWork = false; }
// Watch current set of sources and process events void XmlRpcDispatch::work(double timeout) { // Compute end time _endTime = (timeout < 0.0) ? -1.0 : (getTime() + timeout); _doClear = false; _inWork = true; // Only work while there is something to monitor while (_sources.size() > 0) { // Construct the sets of descriptors we are interested in fd_set inFd, outFd, excFd; FD_ZERO(&inFd); FD_ZERO(&outFd); FD_ZERO(&excFd); int maxFd = -1; // Not used on windows SourceList::iterator it; for (it=_sources.begin(); it!=_sources.end(); ++it) { int fd = it->getSource()->getfd(); if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd); if (it->getMask() & WritableEvent) FD_SET(fd, &outFd); if (it->getMask() & Exception) FD_SET(fd, &excFd); if (it->getMask() && fd > maxFd) maxFd = fd; } // Check for events int nEvents; if (timeout < 0.0) nEvents = select(maxFd+1, &inFd, &outFd, &excFd, NULL); else { struct timeval tv; tv.tv_sec = (int)floor(timeout); tv.tv_usec = ((int)floor(1000000.0 * (timeout-floor(timeout)))) % 1000000; nEvents = select(maxFd+1, &inFd, &outFd, &excFd, &tv); } if (nEvents < 0) { XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents); _inWork = false; return; } // Process events for (it=_sources.begin(); it != _sources.end(); ) { SourceList::iterator thisIt = it++; XmlRpcSource* src = thisIt->getSource(); int fd = src->getfd(); unsigned newMask = (unsigned) -1; if (fd <= maxFd) { // If you select on multiple event types this could be ambiguous if (FD_ISSET(fd, &inFd)) newMask &= src->handleEvent(ReadableEvent); if (FD_ISSET(fd, &outFd)) newMask &= src->handleEvent(WritableEvent); if (FD_ISSET(fd, &excFd)) newMask &= src->handleEvent(Exception); if ( ! newMask) { _sources.erase(thisIt); // Stop monitoring this one if ( ! src->getKeepOpen()) src->close(); } else if (newMask != (unsigned) -1) { thisIt->getMask() = newMask; } } } // Check whether to clear all sources if (_doClear) { SourceList closeList = _sources; _sources.clear(); for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) { XmlRpcSource *src = it->getSource(); src->close(); } _doClear = false; } // Check whether end time has passed if (0 <= _endTime && getTime() > _endTime) break; } _inWork = false; }
int main(int argc, char *argv[]) { FillData fill_data; int fromfile_id = 1; int fromfile_offset = 0; QString fromfile_name; bool from_file = false; bool mark_repeats = true; bool usingDataDirect = false; bool from_dd_file = false; int sourceid = -1; QString fromddfile_lineupid; MythFillDatabaseCommandLineParser cmdline; if (!cmdline.Parse(argc, argv)) { cmdline.PrintHelp(); return GENERIC_EXIT_INVALID_CMDLINE; } if (cmdline.toBool("showhelp")) { cmdline.PrintHelp(); return GENERIC_EXIT_OK; } if (cmdline.toBool("showversion")) { cmdline.PrintVersion(); return GENERIC_EXIT_OK; } QCoreApplication a(argc, argv); QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHFILLDATABASE); myth_nice(19); int retval; if ((retval = cmdline.ConfigureLogging()) != GENERIC_EXIT_OK) return retval; if (cmdline.toBool("manual")) { cout << "###\n"; cout << "### Running in manual channel configuration mode.\n"; cout << "### This will ask you questions about every channel.\n"; cout << "###\n"; fill_data.chan_data.m_interactive = true; } if (cmdline.toBool("onlyguide") || cmdline.toBool("update")) { LOG(VB_GENERAL, LOG_NOTICE, "Only updating guide data, channel and icon updates will be ignored"); fill_data.chan_data.m_guideDataOnly = true; } if (cmdline.toBool("preset")) { cout << "###\n"; cout << "### Running in preset channel configuration mode.\n"; cout << "### This will assign channel "; cout << "preset numbers to every channel.\n"; cout << "###\n"; fill_data.chan_data.m_channelPreset = true; } if (cmdline.toBool("file")) { // manual file mode if (!cmdline.toBool("sourceid") || !cmdline.toBool("xmlfile")) { cerr << "The --file option must be used in combination" << endl << "with both --sourceid and --xmlfile." << endl; return GENERIC_EXIT_INVALID_CMDLINE; } fromfile_id = cmdline.toInt("sourceid"); fromfile_name = cmdline.toString("xmlfile"); LOG(VB_GENERAL, LOG_INFO, "Bypassing grabbers, reading directly from file"); from_file = true; } if (cmdline.toBool("ddfile")) { // datadirect file mode if (!cmdline.toBool("sourceid") || !cmdline.toBool("offset") || !cmdline.toBool("lineupid") || !cmdline.toBool("xmlfile")) { cerr << "The --dd-file option must be used in combination" << endl << "with each of --sourceid, --offset, --lineupid," << endl << "and --xmlfile." << endl; return GENERIC_EXIT_INVALID_CMDLINE; } fromfile_id = cmdline.toInt("sourceid"); fromfile_offset = cmdline.toInt("offset"); fromddfile_lineupid = cmdline.toString("lineupid"); fromfile_name = cmdline.toString("xmlfile"); LOG(VB_GENERAL, LOG_INFO, "Bypassing grabbers, reading directly from file"); from_dd_file = true; } if (cmdline.toBool("dochannelupdates")) fill_data.chan_data.m_channelUpdates = true; if (cmdline.toBool("removechannels")) fill_data.chan_data.m_removeNewChannels = true; if (cmdline.toBool("nofilterchannels")) fill_data.chan_data.m_filterNewChannels = false; if (!cmdline.GetPassthrough().isEmpty()) fill_data.graboptions = " " + cmdline.GetPassthrough(); if (cmdline.toBool("sourceid")) sourceid = cmdline.toInt("sourceid"); if (cmdline.toBool("cardtype")) { if (!cmdline.toBool("sourceid")) { cerr << "The --cardtype option must be used in combination" << endl << "with a --sourceid option." << endl; return GENERIC_EXIT_INVALID_CMDLINE; } fill_data.chan_data.m_cardType = cmdline.toString("cardtype") .trimmed().toUpper(); } if (cmdline.toBool("maxdays") && cmdline.toInt("maxdays") > 0) { fill_data.maxDays = cmdline.toInt("maxdays"); if (fill_data.maxDays == 1) fill_data.SetRefresh(0, true); } if (cmdline.toBool("refreshtoday")) cmdline.SetValue("refresh", cmdline.toStringList("refresh") << "today"); if (cmdline.toBool("dontrefreshtomorrow")) cmdline.SetValue("refresh", cmdline.toStringList("refresh") << "nottomorrow"); if (cmdline.toBool("refreshsecond")) cmdline.SetValue("refresh", cmdline.toStringList("refresh") << "second"); if (cmdline.toBool("refreshall")) cmdline.SetValue("refresh", cmdline.toStringList("refresh") << "all"); if (cmdline.toBool("refreshday")) cmdline.SetValue("refresh", cmdline.toStringList("refresh") << cmdline.toStringList("refreshday")); QStringList sl = cmdline.toStringList("refresh"); if (!sl.isEmpty()) { QStringList::const_iterator i = sl.constBegin(); for (; i != sl.constEnd(); ++i) { QString warn = QString("Invalid entry in --refresh list: %1") .arg(*i); bool enable = (*i).contains("not") ? false : true; if ((*i).contains("today")) fill_data.SetRefresh(0, enable); else if ((*i).contains("tomorrow")) fill_data.SetRefresh(1, enable); else if ((*i).contains("second")) fill_data.SetRefresh(2, enable); else if ((*i).contains("all")) fill_data.SetRefresh(FillData::kRefreshAll, enable); else if ((*i).contains("-")) { bool ok; QStringList r = (*i).split("-"); uint lower = r[0].toUInt(&ok); if (!ok) { cerr << warn.toLocal8Bit().constData() << endl; return false; } uint upper = r[1].toUInt(&ok); if (!ok) { cerr << warn.toLocal8Bit().constData() << endl; return false; } if (lower > upper) { cerr << warn.toLocal8Bit().constData() << endl; return false; } for (uint j = lower; j <= upper; ++j) fill_data.SetRefresh(j, true); } else { bool ok; uint day = (*i).toUInt(&ok); if (!ok) { cerr << warn.toLocal8Bit().constData() << endl; return false; } fill_data.SetRefresh(day, true); } } } if (cmdline.toBool("dontrefreshtba")) fill_data.refresh_tba = false; if (cmdline.toBool("ddgraball")) { fill_data.SetRefresh(FillData::kRefreshClear, false); fill_data.dd_grab_all = true; } if (cmdline.toBool("onlychannels")) fill_data.only_update_channels = true; mark_repeats = cmdline.toBool("markrepeats"); CleanupGuard callCleanup(cleanup); #ifndef _WIN32 QList<int> signallist; signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE << SIGILL; #if ! CONFIG_DARWIN signallist << SIGRTMIN; #endif SignalHandler::Init(signallist); signal(SIGHUP, SIG_IGN); #endif gContext = new MythContext(MYTH_BINARY_VERSION); if (!gContext->Init(false)) { LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting."); return GENERIC_EXIT_NO_MYTHCONTEXT; } setHttpProxy(); MythTranslation::load("mythfrontend"); if (!UpgradeTVDatabaseSchema(false)) { LOG(VB_GENERAL, LOG_ERR, "Incorrect database schema"); return GENERIC_EXIT_DB_OUTOFDATE; } if (gCoreContext->SafeConnectToMasterServer(true, false)) LOG(VB_GENERAL, LOG_INFO, "Opening blocking connection to master backend"); else LOG(VB_GENERAL, LOG_WARNING, "Failed to connect to master backend. MythFillDatabase will " "continue running but will be unable to prevent backend from " "shutting down, or triggering a reschedule when complete."); if (from_file) { QString status = QObject::tr("currently running."); QDateTime GuideDataBefore, GuideDataAfter; updateLastRunStart(); updateLastRunStatus(status); MSqlQuery query(MSqlQuery::InitCon()); query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c " "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID " "AND manualid = 0 AND c.xmltvid != '';"); query.bindValue(":SRCID", fromfile_id); if (query.exec() && query.next()) { if (!query.isNull(0)) GuideDataBefore = MythDate::fromString(query.value(0).toString()); } if (!fill_data.GrabDataFromFile(fromfile_id, fromfile_name)) { return GENERIC_EXIT_NOT_OK; } updateLastRunEnd(); query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c " "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID " "AND manualid = 0 AND c.xmltvid != '';"); query.bindValue(":SRCID", fromfile_id); if (query.exec() && query.next()) { if (!query.isNull(0)) GuideDataAfter = MythDate::fromString(query.value(0).toString()); } if (GuideDataAfter == GuideDataBefore) status = QObject::tr("mythfilldatabase ran, but did not insert " "any new data into the Guide. This can indicate a " "potential problem with the XML file used for the update."); else status = QObject::tr("Successful."); updateLastRunStatus(status); } else if (from_dd_file) { fill_data.GrabDataFromDDFile( fromfile_id, fromfile_offset, fromfile_name, fromddfile_lineupid); } else { SourceList sourcelist; MSqlQuery sourcequery(MSqlQuery::InitCon()); QString where; if (sourceid != -1) { LOG(VB_GENERAL, LOG_INFO, QString("Running for sourceid %1 ONLY because --sourceid " "was given on command-line").arg(sourceid)); where = QString("WHERE sourceid = %1").arg(sourceid); } QString querystr = QString("SELECT sourceid,name,xmltvgrabber,userid," "password,lineupid " "FROM videosource ") + where + QString(" ORDER BY sourceid;"); if (sourcequery.exec(querystr)) { if (sourcequery.size() > 0) { while (sourcequery.next()) { Source newsource; newsource.id = sourcequery.value(0).toInt(); newsource.name = sourcequery.value(1).toString(); newsource.xmltvgrabber = sourcequery.value(2).toString(); newsource.userid = sourcequery.value(3).toString(); newsource.password = sourcequery.value(4).toString(); newsource.lineupid = sourcequery.value(5).toString(); newsource.xmltvgrabber_baseline = false; newsource.xmltvgrabber_manualconfig = false; newsource.xmltvgrabber_cache = false; newsource.xmltvgrabber_prefmethod = ""; sourcelist.push_back(newsource); usingDataDirect |= is_grabber_datadirect(newsource.xmltvgrabber); } } else { LOG(VB_GENERAL, LOG_ERR, "There are no channel sources defined, did you run " "the setup program?"); return GENERIC_EXIT_SETUP_ERROR; } } else { MythDB::DBError("loading channel sources", sourcequery); return GENERIC_EXIT_DB_ERROR; } if (!fill_data.Run(sourcelist)) LOG(VB_GENERAL, LOG_ERR, "Failed to fetch some program info"); else LOG(VB_GENERAL, LOG_NOTICE, "Data fetching complete."); } if (fill_data.only_update_channels && !fill_data.need_post_grab_proc) { return GENERIC_EXIT_OK; } LOG(VB_GENERAL, LOG_INFO, "Adjusting program database end times."); int update_count = ProgramData::fix_end_times(); if (update_count == -1) LOG(VB_GENERAL, LOG_ERR, "fix_end_times failed!"); else LOG(VB_GENERAL, LOG_INFO, QString(" %1 replacements made").arg(update_count)); LOG(VB_GENERAL, LOG_INFO, "Marking generic episodes."); MSqlQuery query(MSqlQuery::InitCon()); query.prepare("UPDATE program SET generic = 1 WHERE " "((programid = '' AND subtitle = '' AND description = '') OR " " (programid <> '' AND category_type = 'series' AND " " program.programid LIKE '%0000'));"); if (!query.exec()) MythDB::DBError("mark generic", query); else LOG(VB_GENERAL, LOG_INFO, QString(" Found %1").arg(query.numRowsAffected())); LOG(VB_GENERAL, LOG_INFO, "Extending non-unique programids " "with multiple parts."); int found = 0; MSqlQuery sel(MSqlQuery::InitCon()); sel.prepare("SELECT DISTINCT programid, partnumber, parttotal " "FROM program WHERE partnumber > 0 AND parttotal > 0 AND " "programid LIKE '%0000'"); if (sel.exec()) { MSqlQuery repl(MSqlQuery::InitCon()); repl.prepare("UPDATE program SET programid = :NEWID " "WHERE programid = :OLDID AND " "partnumber = :PARTNUM AND " "parttotal = :PARTTOTAL"); while (sel.next()) { QString orig_programid = sel.value(0).toString(); QString new_programid = orig_programid.left(10); int partnum, parttotal; QString part; partnum = sel.value(1).toInt(); parttotal = sel.value(2).toInt(); part.setNum(parttotal); new_programid.append(part.rightJustified(2, '0')); part.setNum(partnum); new_programid.append(part.rightJustified(2, '0')); LOG(VB_GENERAL, LOG_INFO, QString(" %1 -> %2 (part %3 of %4)") .arg(orig_programid).arg(new_programid) .arg(partnum).arg(parttotal)); repl.bindValue(":NEWID", new_programid); repl.bindValue(":OLDID", orig_programid); repl.bindValue(":PARTNUM", partnum); repl.bindValue(":PARTTOTAL", parttotal); if (!repl.exec()) { LOG(VB_GENERAL, LOG_INFO, QString("Fudging programid from '%1' to '%2'") .arg(orig_programid) .arg(new_programid)); } else found += repl.numRowsAffected(); } } LOG(VB_GENERAL, LOG_INFO, QString(" Found %1").arg(found)); LOG(VB_GENERAL, LOG_INFO, "Fixing missing original airdates."); query.prepare("UPDATE program p " "JOIN ( " " SELECT programid, MAX(originalairdate) maxoad " " FROM program " " WHERE programid <> '' AND " " originalairdate IS NOT NULL " " GROUP BY programid ) oad " " ON p.programid = oad.programid " "SET p.originalairdate = oad.maxoad " "WHERE p.originalairdate IS NULL"); if (query.exec()) LOG(VB_GENERAL, LOG_INFO, QString(" Found %1 with programids") .arg(query.numRowsAffected())); query.prepare("UPDATE program p " "JOIN ( " " SELECT title, subtitle, description, " " MAX(originalairdate) maxoad " " FROM program " " WHERE programid = '' AND " " originalairdate IS NOT NULL " " GROUP BY title, subtitle, description ) oad " " ON p.programid = '' AND " " p.title = oad.title AND " " p.subtitle = oad.subtitle AND " " p.description = oad.description " "SET p.originalairdate = oad.maxoad " "WHERE p.originalairdate IS NULL"); if (query.exec()) LOG(VB_GENERAL, LOG_INFO, QString(" Found %1 without programids") .arg(query.numRowsAffected())); if (mark_repeats) { LOG(VB_GENERAL, LOG_INFO, "Marking repeats."); int newEpiWindow = gCoreContext->GetNumSetting( "NewEpisodeWindow", 14); MSqlQuery query(MSqlQuery::InitCon()); query.prepare("UPDATE program SET previouslyshown = 1 " "WHERE previouslyshown = 0 " "AND originalairdate is not null " "AND (to_days(starttime) - to_days(originalairdate)) " " > :NEWWINDOW;"); query.bindValue(":NEWWINDOW", newEpiWindow); if (query.exec()) LOG(VB_GENERAL, LOG_INFO, QString(" Found %1").arg(query.numRowsAffected())); LOG(VB_GENERAL, LOG_INFO, "Unmarking new episode rebroadcast repeats."); query.prepare("UPDATE program SET previouslyshown = 0 " "WHERE previouslyshown = 1 " "AND originalairdate is not null " "AND (to_days(starttime) - to_days(originalairdate)) " " <= :NEWWINDOW;"); query.bindValue(":NEWWINDOW", newEpiWindow); if (query.exec()) LOG(VB_GENERAL, LOG_INFO, QString(" Found %1").arg(query.numRowsAffected())); } // Mark first and last showings MSqlQuery updt(MSqlQuery::InitCon()); updt.prepare("UPDATE program SET first = 0, last = 0;"); if (!updt.exec()) MythDB::DBError("Clearing first and last showings", updt); LOG(VB_GENERAL, LOG_INFO, "Marking episode first showings."); updt.prepare("UPDATE program " "JOIN (SELECT MIN(p.starttime) AS starttime, p.programid " " FROM program p, channel c " " WHERE p.programid <> '' " " AND p.chanid = c.chanid " " AND c.visible = 1 " " GROUP BY p.programid " " ) AS firsts " "ON program.programid = firsts.programid " " AND program.starttime = firsts.starttime " "SET program.first=1;"); if (!updt.exec()) MythDB::DBError("Marking first showings by id", updt); found = updt.numRowsAffected(); updt.prepare("UPDATE program " "JOIN (SELECT MIN(p.starttime) AS starttime, p.title, p.subtitle, " " LEFT(p.description, 1024) AS partdesc " " FROM program p, channel c " " WHERE p.programid = '' " " AND p.chanid = c.chanid " " AND c.visible = 1 " " GROUP BY p.title, p.subtitle, partdesc " " ) AS firsts " "ON program.starttime = firsts.starttime " " AND program.title = firsts.title " " AND program.subtitle = firsts.subtitle " " AND LEFT(program.description, 1024) = firsts.partdesc " "SET program.first = 1 " "WHERE program.programid = '';"); if (!updt.exec()) MythDB::DBError("Marking first showings", updt); found += updt.numRowsAffected(); LOG(VB_GENERAL, LOG_INFO, QString(" Found %1").arg(found)); LOG(VB_GENERAL, LOG_INFO, "Marking episode last showings."); updt.prepare("UPDATE program " "JOIN (SELECT MAX(p.starttime) AS starttime, p.programid " " FROM program p, channel c " " WHERE p.programid <> '' " " AND p.chanid = c.chanid " " AND c.visible = 1 " " GROUP BY p.programid " " ) AS lasts " "ON program.programid = lasts.programid " " AND program.starttime = lasts.starttime " "SET program.last=1;"); if (!updt.exec()) MythDB::DBError("Marking last showings by id", updt); found = updt.numRowsAffected(); updt.prepare("UPDATE program " "JOIN (SELECT MAX(p.starttime) AS starttime, p.title, p.subtitle, " " LEFT(p.description, 1024) AS partdesc " " FROM program p, channel c " " WHERE p.programid = '' " " AND p.chanid = c.chanid " " AND c.visible = 1 " " GROUP BY p.title, p.subtitle, partdesc " " ) AS lasts " "ON program.starttime = lasts.starttime " " AND program.title = lasts.title " " AND program.subtitle = lasts.subtitle " " AND LEFT(program.description, 1024) = lasts.partdesc " "SET program.last = 1 " "WHERE program.programid = '';"); if (!updt.exec()) MythDB::DBError("Marking last showings", updt); found += updt.numRowsAffected(); LOG(VB_GENERAL, LOG_INFO, QString(" Found %1").arg(found)); if (1) // limit MSqlQuery's lifetime { MSqlQuery query(MSqlQuery::InitCon()); query.prepare("SELECT count(previouslyshown) " "FROM program WHERE previouslyshown = 1;"); if (query.exec() && query.next()) { if (query.value(0).toInt() != 0) gCoreContext->SaveSettingOnHost("HaveRepeats", "1", NULL); else gCoreContext->SaveSettingOnHost("HaveRepeats", "0", NULL); } } if ((usingDataDirect) && (gCoreContext->GetNumSetting("MythFillGrabberSuggestsTime", 1))) { fill_data.ddprocessor.GrabNextSuggestedTime(); } LOG(VB_GENERAL, LOG_INFO, "\n" "===============================================================\n" "| Attempting to contact the master backend for rescheduling. |\n" "| If the master is not running, rescheduling will happen when |\n" "| the master backend is restarted. |\n" "==============================================================="); if (mark_repeats) ScheduledRecording::RescheduleMatch(0, 0, 0, QDateTime(), "MythFillDatabase"); gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE"); gCoreContext->SendSystemEvent("MYTHFILLDATABASE_RAN"); LOG(VB_GENERAL, LOG_NOTICE, "mythfilldatabase run complete."); return GENERIC_EXIT_OK; }
void NITFWriteControl::save( SourceList& imageData, nitf::IOInterface& outputFile, const std::vector<std::string>& schemaPaths) { mWriter.prepareIO(outputFile, mRecord); bool doByteSwap; int byteSwapping = (int) mOptions.getParameter(OPT_BYTE_SWAP, Parameter((int) ByteSwapping::SWAP_AUTO)); if (byteSwapping == ByteSwapping::SWAP_AUTO) { // Have to if its not a BE machine doByteSwap = !sys::isBigEndianSystem(); } else { // Do what they say. You really shouldnt do this // unless you know what you're doing anyway! doByteSwap = byteSwapping ? true : false; } if (mInfos.size() != imageData.size()) { std::ostringstream ostr; ostr << "Require " << mInfos.size() << " images, received " << imageData.size(); throw except::Exception(Ctxt(ostr.str())); } size_t numImages = mInfos.size(); //! TODO: This section of code (unlike the memory section below) // does not account for blocked writing or J2K compression. // CODA ticket #443 will update support for this. for (size_t i = 0; i < numImages; ++i) { NITFImageInfo* info = mInfos[i]; std::vector < NITFSegmentInfo > imageSegments = info->getImageSegments(); size_t numIS = imageSegments.size(); size_t pixelSize = info->getData()->getNumBytesPerPixel(); size_t numCols = info->getData()->getNumCols(); size_t numChannels = info->getData()->getNumChannels(); for (size_t j = 0; j < numIS; ++j) { NITFSegmentInfo segmentInfo = imageSegments[j]; mem::SharedPtr< ::nitf::WriteHandler> writeHandler( new StreamWriteHandler (segmentInfo, imageData[i], numCols, numChannels, pixelSize, doByteSwap)); mWriter.setImageWriteHandler(info->getStartIndex() + j, writeHandler); } } addDataAndWrite(schemaPaths); }
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); FillData fill_data; int argpos = 1; int fromfile_id = 1; int fromfile_offset = 0; QString fromfile_name; bool from_xawfile = false; int fromxawfile_id = 1; QString fromxawfile_name; bool from_file = false; bool mark_repeats = true; bool usingDataDirect = false; bool grab_data = true; bool export_iconmap = false; bool import_iconmap = false; bool reset_iconmap = false; bool reset_iconmap_icons = false; QString import_icon_data_filename("iconmap.xml"); QString export_icon_data_filename("iconmap.xml"); bool update_icon_data = false; bool from_dd_file = false; int sourceid = -1; QString fromddfile_lineupid; QFileInfo finfo(a.argv()[0]); QString binname = finfo.baseName(); myth_nice(19); while (argpos < a.argc()) { // The manual and update flags should be mutually exclusive. if (!strcmp(a.argv()[argpos], "--manual")) { cout << "###\n"; cout << "### Running in manual channel configuration mode.\n"; cout << "### This will ask you questions about every channel.\n"; cout << "###\n"; fill_data.chan_data.interactive = true; } else if (!strcmp(a.argv()[argpos], "--preset")) { // For using channel preset values instead of channel numbers. cout << "###\n"; cout << "### Running in preset channel configuration mode.\n"; cout << "### This will assign channel "; cout << "preset numbers to every channel.\n"; cout << "###\n"; fill_data.chan_data.channel_preset = true; } else if (!strcmp(a.argv()[argpos], "--update")) { // For running non-destructive updates on the database for // users in xmltv zones that do not provide channel data. fill_data.chan_data.non_us_updating = true; } else if (!strcmp(a.argv()[argpos], "--file")) { if (((argpos + 2) >= a.argc()) || !strncmp(a.argv()[argpos + 1], "--", 2) || !strncmp(a.argv()[argpos + 2], "--", 2)) { printf("missing or invalid parameters for --file option\n"); return FILLDB_EXIT_INVALID_CMDLINE; } if (!fromfile_name.isEmpty()) { printf("only one --file option allowed\n"); return FILLDB_EXIT_INVALID_CMDLINE; } fromfile_id = atoi(a.argv()[++argpos]); fromfile_name = a.argv()[++argpos]; VERBOSE(VB_GENERAL, "Bypassing grabbers, reading directly from file"); from_file = true; } else if (!strcmp(a.argv()[argpos], "--dd-file")) { if (((argpos + 4) >= a.argc()) || !strncmp(a.argv()[argpos + 1], "--", 2) || !strncmp(a.argv()[argpos + 2], "--", 2) || !strncmp(a.argv()[argpos + 3], "--", 2) || !strncmp(a.argv()[argpos + 4], "--", 2)) { printf("missing or invalid parameters for --dd-file option\n"); return FILLDB_EXIT_INVALID_CMDLINE; } if (!fromfile_name.isEmpty()) { printf("only one --dd-file option allowed\n"); return FILLDB_EXIT_INVALID_CMDLINE; } fromfile_id = atoi(a.argv()[++argpos]); fromfile_offset = atoi(a.argv()[++argpos]); fromddfile_lineupid = a.argv()[++argpos]; fromfile_name = a.argv()[++argpos]; VERBOSE(VB_GENERAL, "Bypassing grabbers, reading directly from file"); from_dd_file = true; } else if (!strcmp(a.argv()[argpos], "--xawchannels")) { if (((argpos + 2) >= a.argc()) || !strncmp(a.argv()[argpos + 1], "--", 2) || !strncmp(a.argv()[argpos + 2], "--", 2)) { printf("missing or invalid parameters for --xawchannels option\n"); return FILLDB_EXIT_INVALID_CMDLINE; } if (!fromxawfile_name.isEmpty()) { printf("only one --xawchannels option allowed\n"); return FILLDB_EXIT_INVALID_CMDLINE; } fromxawfile_id = atoi(a.argv()[++argpos]); fromxawfile_name = a.argv()[++argpos]; VERBOSE(VB_GENERAL, "Reading channels from xawtv configfile"); from_xawfile = true; } else if (!strcmp(a.argv()[argpos], "--do-channel-updates")) { fill_data.chan_data.channel_updates = true; } else if (!strcmp(a.argv()[argpos], "--remove-new-channels")) { fill_data.chan_data.remove_new_channels = true; } else if (!strcmp(a.argv()[argpos], "--do-not-filter-new-channels")) { fill_data.chan_data.filter_new_channels = false; } else if (!strcmp(a.argv()[argpos], "--graboptions")) { if (((argpos + 1) >= a.argc())) { printf("missing parameter for --graboptions option\n"); return FILLDB_EXIT_INVALID_CMDLINE; } fill_data.graboptions = QString(" ") + QString(a.argv()[++argpos]); } else if (!strcmp(a.argv()[argpos], "--sourceid")) { if (((argpos + 1) >= a.argc())) { printf("missing parameter for --sourceid option\n"); return FILLDB_EXIT_INVALID_CMDLINE; } sourceid = QString(a.argv()[++argpos]).toInt(); } else if (!strcmp(a.argv()[argpos], "--cardtype")) { if (!sourceid) { printf("--cardtype option must follow a --sourceid option\n"); return FILLDB_EXIT_INVALID_CMDLINE; } if (((argpos + 1) >= a.argc())) { printf("missing parameter for --cardtype option\n"); return FILLDB_EXIT_INVALID_CMDLINE; } fill_data.chan_data.cardtype = QString(a.argv()[++argpos]).trimmed().toUpper(); } else if (!strcmp(a.argv()[argpos], "--max-days")) { if (((argpos + 1) >= a.argc())) { printf("missing parameter for --max-days option\n"); return FILLDB_EXIT_INVALID_CMDLINE; } fill_data.maxDays = QString(a.argv()[++argpos]).toUInt(); if (fill_data.maxDays < 1) { printf("ignoring invalid parameter for --max-days\n"); fill_data.maxDays = 0; } else if (fill_data.maxDays == 1) { fill_data.SetRefresh(0, true); } } else if (!strcmp(a.argv()[argpos], "--refresh-today")) { fill_data.SetRefresh(0, true); } else if (!strcmp(a.argv()[argpos], "--dont-refresh-tomorrow")) { fill_data.SetRefresh(1, false); } else if (!strcmp(a.argv()[argpos], "--refresh-second")) { fill_data.SetRefresh(2, true); } else if (!strcmp(a.argv()[argpos], "--refresh-all")) { fill_data.SetRefresh(FillData::kRefreshAll, true); } else if (!strcmp(a.argv()[argpos], "--refresh-day")) { if (((argpos + 1) >= a.argc())) { printf("missing parameter for --refresh-day option\n"); return FILLDB_EXIT_INVALID_CMDLINE; } bool ok = true; uint day = QString(a.argv()[++argpos]).toUInt(&ok); if (!ok) { printf("ignoring invalid parameter for --refresh-day\n"); } else { fill_data.SetRefresh(day, true); } } else if (!strcmp(a.argv()[argpos], "--dont-refresh-tba")) { fill_data.refresh_tba = false; } else if (!strcmp(a.argv()[argpos], "--only-update-channels")) { fill_data.only_update_channels = true; } 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 GENERIC_EXIT_INVALID_CMDLINE; ++argpos; } else { cerr << "Missing argument to -v/--verbose option\n"; return GENERIC_EXIT_INVALID_CMDLINE; } } else if (!strcmp(a.argv()[argpos], "--dd-grab-all")) { fill_data.SetRefresh(FillData::kRefreshClear, false); fill_data.dd_grab_all = true; } else if (!strcmp(a.argv()[argpos], "--quiet")) { print_verbose_messages = VB_NONE; } else if (!strcmp(a.argv()[argpos], "--mark-repeats")) { mark_repeats = true; } else if (!strcmp(a.argv()[argpos], "--nomark-repeats")) { mark_repeats = false; } else if (!strcmp(a.argv()[argpos], "--export-icon-map")) { export_iconmap = true; grab_data = false; if ((argpos + 1) >= a.argc() || !strncmp(a.argv()[argpos + 1], "--", 2)) { if (!isatty(fileno(stdout))) { export_icon_data_filename = '-'; } } else { export_icon_data_filename = a.argv()[++argpos]; } } else if (!strcmp(a.argv()[argpos], "--import-icon-map")) { import_iconmap = true; grab_data = false; if ((argpos + 1) >= a.argc() || !strncmp(a.argv()[argpos + 1], "--", 2)) { if (!isatty(fileno(stdin))) { import_icon_data_filename = '-'; } } else { import_icon_data_filename = a.argv()[++argpos]; } } else if (!strcmp(a.argv()[argpos], "--update-icon-map")) { update_icon_data = true; grab_data = false; } else if (!strcmp(a.argv()[argpos], "--reset-icon-map")) { reset_iconmap = true; grab_data = false; if ((argpos + 1) < a.argc() && strncmp(a.argv()[argpos + 1], "--", 2)) { ++argpos; if (QString(a.argv()[argpos]) == "all") { reset_iconmap_icons = true; } else { cerr << "Unknown icon group '" << a.argv()[argpos] << "' for --reset-icon-map option" << endl; return FILLDB_EXIT_UNKNOWN_ICON_GROUP; } } } else if (!strcmp(a.argv()[argpos], "-h") || !strcmp(a.argv()[argpos], "--help")) { cout << "usage:\n"; cout << "--manual\n"; cout << " Run in manual channel configuration mode\n"; cout << " This will ask you questions about every channel\n"; cout << "\n"; cout << "--update\n"; cout << " For running non-destructive updates on the database for\n"; cout << " users in xmltv zones that do not provide channel data\n"; cout << " Stops the addition of new channels and the changing of channel icons.\n"; cout << "\n"; cout << "--preset\n"; cout << " Use it in case that you want to assign a preset number for\n"; cout << " each channel, useful for non US countries where people\n"; cout << " are used to assigning a sequenced number for each channel, i.e.:\n"; cout << " 1->TVE1(S41), 2->La 2(SE18), 3->TV3(21), 4->Canal 33(60)...\n"; cout << "\n"; cout << "--file <sourceid> <xmlfile>\n"; cout << " Bypass the grabbers and read data directly from a file\n"; cout << " <sourceid> = number of the video source to use with this file\n"; cout << " <xmlfile> = file to read\n"; cout << "\n"; cout << "--dd-file <sourceid> <offset> <lineupid> <xmlfile>\n"; cout << " <sourceid> = number of the video source to use with this file\n"; cout << " <offset> = days from today that xmlfile defines\n"; cout << " (-1 means to replace all data, up to 10 days)\n"; cout << " <lineupid> = the lineup id\n"; cout << " <xmlfile> = file to read\n"; cout << "\n"; cout << "--xawchannels <sourceid> <xawtvrcfile>\n"; cout << " (--manual flag works in combination with this)\n"; cout << " Read channels as defined in xawtvrc file given\n"; cout << " <sourceid> = cardinput\n"; cout << " <xawtvrcfile> = file to read\n"; cout << "\n"; cout << "--do-channel-updates\n"; cout << " When using DataDirect, ask mythfilldatabase to\n"; cout << " overwrite channel names, frequencies, etc. with the\n"; cout << " values available from the data source. This will \n"; cout << " override custom channel names, which is why it is\n"; cout << " off by default.\n"; cout << "\n"; cout << "--remove-new-channels\n"; cout << " When using DataDirect, ask mythfilldatabase to\n"; cout << " remove new channels (those not in the database)\n"; cout << " from the DataDirect lineup. These channels are\n"; cout << " removed from the lineup as if you had done so\n"; cout << " via the DataDirect website's Lineup Wizard, but\n"; cout << " may be re-added manually and incorporated into\n"; cout << " MythTV by running mythfilldatabase without this\n"; cout << " option. New channels are automatically removed\n"; cout << " for DVB and HDTV sources that use DataDirect.\n"; cout << "\n"; cout << "--do-not-filter-new-channels\n"; cout << " Normally MythTV tries to avoid adding ATSC channels\n"; cout << " to NTSC channel lineups. This option restores the\n"; cout << " behaviour of adding every channel in the downloaded\n"; cout << " channel lineup to MythTV's lineup, in case MythTV's\n"; cout << " smarts fail you.\n"; cout << "\n"; cout << "--graboptions <\"options\">\n"; cout << " Pass options to grabber. Do NOT use unless you know\n"; cout << " what you are doing. Mythfilldatabase will\n"; cout << " automatically use the correct options for xmltv\n"; cout << " compliant grabbers.\n"; cout << "\n"; cout << "--sourceid <number>\n"; cout << " Only refresh data for sourceid given\n"; cout << "\n"; cout << "--max-days <number>\n"; cout << " Force the maximum number of days, counting today,\n"; cout << " for the grabber to check for future listings\n"; cout << "--only-update-channels\n"; cout << " Get as little listings data as possible to update channels\n"; cout << "--refresh-today\n"; cout << "--refresh-second\n"; cout << "--refresh-all\n"; cout << "--refresh-day <number>"; cout << " (Only valid for selected grabbers: e.g. DataDirect)\n"; cout << " Force a refresh today, two days, every day, or a specific day from now,\n"; cout << " to catch the latest changes. --refresh-all will update every day except\n"; cout << " the current day. To refresh today and all following days, XMLTV users\n"; cout << " should combine --refresh-today and --refresh-all. Schedules Direct/\n"; cout << " DataDirect users should use --dd-grab-all.\n"; cout << "--dont-refresh-tomorrow\n"; cout << " Tomorrow will always be refreshed unless this argument is used\n"; cout << "--dont-refresh-tba\n"; cout << " \"To be announced\" programs will always be refreshed \n"; cout << " unless this argument is used\n"; cout << "\n"; cout << "--dd-grab-all\n"; cout << " The DataDirect grabber will grab all available data\n"; cout << " in a single pull. This will ensure you always have\n"; cout << " the most up-to-date data, but requires significantly\n"; cout << " more CPU and RAM. It is not expected to work on all\n"; cout << " backend systems and with all lineups, and may\n"; cout << " interfere with recording due to resource starvation.\n"; cout << "\n"; cout << "--export-icon-map [<filename>]\n"; cout << " Exports your current icon map to <filename> (default: " << export_icon_data_filename.toLocal8Bit().constData() << ")\n"; cout << "--import-icon-map [<filename>]\n"; cout << " Imports an icon map from <filename> (default: " << import_icon_data_filename.toLocal8Bit().constData() << ")\n"; cout << "--update-icon-map\n"; cout << " Updates icon map icons only\n"; cout << "--reset-icon-map [all]\n"; cout << " Resets your icon map (pass all to reset channel icons as well)\n"; cout << "\n"; cout << "--mark-repeats\n"; cout << " Marks any programs with a OriginalAirDate earlier\n"; cout << " than their start date as a repeat\n"; cout << "\n"; cout << "-v or --verbose debug-level\n"; cout << " Use '-v help' for level info\n"; cout << "\n"; cout << "--help\n"; cout << " This text\n"; cout << "\n"; cout << "\n"; cout << " --manual and --update cannot be used together.\n"; cout << "\n"; return FILLDB_EXIT_INVALID_CMDLINE; } else if (!strcmp(a.argv()[argpos], "--no-delete")) { cerr << "Deprecated option '" << a.argv()[argpos] << "'" << endl; } #ifdef Q_WS_MACX else if (!strncmp(argv[argpos],"-psn_",5)) { cerr << "Ignoring Process Serial Number from command line\n"; } #endif else { fprintf(stderr, "illegal option: '%s' (use --help)\n", a.argv()[argpos]); return FILLDB_EXIT_INVALID_CMDLINE; } ++argpos; } CleanupGuard callCleanup(cleanup); gContext = new MythContext(MYTH_BINARY_VERSION); if (!gContext->Init(false)) { VERBOSE(VB_IMPORTANT, "Failed to init MythContext, exiting."); return FILLDB_EXIT_NO_MYTHCONTEXT; } gCoreContext->SetAppName(binname); MythTranslation::load("mythfrontend"); if (!UpgradeTVDatabaseSchema(false)) { VERBOSE(VB_IMPORTANT, "Incorrect database schema"); return GENERIC_EXIT_DB_OUTOFDATE; } gCoreContext->LogEntry("mythfilldatabase", LP_INFO, "Listings Download Started", ""); if (!grab_data) { } else if (from_xawfile) { fill_data.readXawtvChannels(fromxawfile_id, fromxawfile_name); } else if (from_file) { QString status = QObject::tr("currently running."); QDateTime GuideDataBefore, GuideDataAfter; MSqlQuery query(MSqlQuery::InitCon()); updateLastRunStart(query); updateLastRunStatus(query, status); query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c " "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID " "AND manualid = 0;"); query.bindValue(":SRCID", fromfile_id); if (query.exec() && query.next()) { if (!query.isNull(0)) GuideDataBefore = QDateTime::fromString(query.value(0).toString(), Qt::ISODate); } if (!fill_data.GrabDataFromFile(fromfile_id, fromfile_name)) { return FILLDB_EXIT_GRAB_DATA_FAILED; } updateLastRunEnd(query); query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c " "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID " "AND manualid = 0;"); query.bindValue(":SRCID", fromfile_id); if (query.exec() && query.next()) { if (!query.isNull(0)) GuideDataAfter = QDateTime::fromString(query.value(0).toString(), Qt::ISODate); } if (GuideDataAfter == GuideDataBefore) status = QObject::tr("mythfilldatabase ran, but did not insert " "any new data into the Guide. This can indicate a " "potential problem with the XML file used for the update."); else status = QObject::tr("Successful."); updateLastRunStatus(query, status); } else if (from_dd_file) { fill_data.GrabDataFromDDFile( fromfile_id, fromfile_offset, fromfile_name, fromddfile_lineupid); } else { SourceList sourcelist; MSqlQuery sourcequery(MSqlQuery::InitCon()); QString where = ""; if (sourceid != -1) { VERBOSE(VB_GENERAL, QString("Running for sourceid %1 ONLY because --sourceid " "was given on command-line").arg(sourceid)); where = QString("WHERE sourceid = %1").arg(sourceid); } QString querystr = QString("SELECT sourceid,name,xmltvgrabber,userid," "password,lineupid " "FROM videosource ") + where + QString(" ORDER BY sourceid;"); if (sourcequery.exec(querystr)) { if (sourcequery.size() > 0) { while (sourcequery.next()) { Source newsource; newsource.id = sourcequery.value(0).toInt(); newsource.name = sourcequery.value(1).toString(); newsource.xmltvgrabber = sourcequery.value(2).toString(); newsource.userid = sourcequery.value(3).toString(); newsource.password = sourcequery.value(4).toString(); newsource.lineupid = sourcequery.value(5).toString(); newsource.xmltvgrabber_baseline = false; newsource.xmltvgrabber_manualconfig = false; newsource.xmltvgrabber_cache = false; newsource.xmltvgrabber_prefmethod = ""; sourcelist.push_back(newsource); usingDataDirect |= is_grabber_datadirect(newsource.xmltvgrabber); } } else { VERBOSE(VB_IMPORTANT, "There are no channel sources defined, did you run " "the setup program?"); gCoreContext->LogEntry("mythfilldatabase", LP_CRITICAL, "No channel sources defined", "Could not find any defined channel " "sources - did you run the setup " "program?"); return FILLDB_EXIT_NO_CHAN_SRC; } } else { MythDB::DBError("loading channel sources", sourcequery); return FILLDB_EXIT_DB_ERROR; } if (!fill_data.Run(sourcelist)) { VERBOSE(VB_IMPORTANT, "Failed to fetch some program info"); gCoreContext->LogEntry("mythfilldatabase", LP_WARNING, "Failed to fetch some program info", ""); } else VERBOSE(VB_IMPORTANT, "Data fetching complete."); } if (fill_data.only_update_channels && !fill_data.need_post_grab_proc) { return FILLDB_EXIT_OK; } if (reset_iconmap) { fill_data.icon_data.ResetIconMap(reset_iconmap_icons); } if (import_iconmap) { fill_data.icon_data.ImportIconMap(import_icon_data_filename); } if (export_iconmap) { fill_data.icon_data.ExportIconMap(export_icon_data_filename); } if (update_icon_data) { MSqlQuery query(MSqlQuery::InitCon()); query.prepare("SELECT sourceid FROM videosource ORDER BY sourceid"); if (!query.exec()) { MythDB::DBError("Querying sources", query); return FILLDB_EXIT_DB_ERROR; } while (query.next()) fill_data.icon_data.UpdateSourceIcons(query.value(0).toInt()); } if (grab_data) { VERBOSE(VB_GENERAL, "Adjusting program database end times."); int update_count = ProgramData::fix_end_times(); if (update_count == -1) VERBOSE(VB_IMPORTANT, "fix_end_times failed!"); else VERBOSE(VB_GENERAL, QString(" %1 replacements made").arg(update_count)); gCoreContext->LogEntry("mythfilldatabase", LP_INFO, "Listings Download Finished", ""); } if (grab_data) { VERBOSE(VB_GENERAL, "Marking generic episodes."); MSqlQuery query(MSqlQuery::InitCon()); query.prepare("UPDATE program SET generic = 1 WHERE " "((programid = '' AND subtitle = '' AND description = '') OR " " (programid <> '' AND category_type = 'series' AND " " program.programid LIKE '%0000'));"); if (!query.exec()) MythDB::DBError("mark generic", query); else VERBOSE(VB_GENERAL, QString(" Found %1").arg(query.numRowsAffected())); } if (grab_data) { VERBOSE(VB_GENERAL, "Fudging non-unique programids " "with multiple parts."); int found = 0; MSqlQuery sel(MSqlQuery::InitCon()); sel.prepare("SELECT DISTINCT programid, partnumber, parttotal " "FROM program WHERE partnumber > 0 AND parttotal > 0 AND " "programid LIKE '%0000'"); if (sel.exec()) { MSqlQuery repl(MSqlQuery::InitCon()); while (sel.next()) { QString orig_programid = sel.value(0).toString(); QString new_programid = orig_programid.left(10); int partnum, parttotal; QString part; partnum = sel.value(1).toInt(); parttotal = sel.value(2).toInt(); part.setNum(parttotal); new_programid.append(part.rightJustified(2, '0')); part.setNum(partnum); new_programid.append(part.rightJustified(2, '0')); VERBOSE(VB_GENERAL, QString(" %1 -> %2 (part %3 of %4)") .arg(orig_programid).arg(new_programid) .arg(partnum).arg(parttotal)); repl.prepare("UPDATE program SET programid = :NEWID " "WHERE programid = :OLDID AND " "partnumber = :PARTNUM AND " "parttotal = :PARTTOTAL"); repl.bindValue(":NEWID", new_programid); repl.bindValue(":OLDID", orig_programid); repl.bindValue(":PARTNUM", partnum); repl.bindValue(":PARTTOTAL", parttotal); if (!repl.exec()) { VERBOSE(VB_GENERAL, QString("Fudging programid from '%1' to '%2'") .arg(orig_programid) .arg(new_programid)); } else found += repl.numRowsAffected(); } } VERBOSE(VB_GENERAL, QString(" Found %1").arg(found)); } if (mark_repeats) { VERBOSE(VB_GENERAL, "Marking repeats."); int newEpiWindow = gCoreContext->GetNumSetting( "NewEpisodeWindow", 14); MSqlQuery query(MSqlQuery::InitCon()); query.prepare("UPDATE program SET previouslyshown = 1 " "WHERE previouslyshown = 0 " "AND originalairdate is not null " "AND (to_days(starttime) - to_days(originalairdate)) " " > :NEWWINDOW;"); query.bindValue(":NEWWINDOW", newEpiWindow); if (query.exec()) VERBOSE(VB_GENERAL, QString(" Found %1").arg(query.numRowsAffected())); VERBOSE(VB_GENERAL, "Unmarking new episode rebroadcast repeats."); query.prepare("UPDATE program SET previouslyshown = 0 " "WHERE previouslyshown = 1 " "AND originalairdate is not null " "AND (to_days(starttime) - to_days(originalairdate)) " " <= :NEWWINDOW;"); query.bindValue(":NEWWINDOW", newEpiWindow); if (query.exec()) VERBOSE(VB_GENERAL, QString(" Found %1").arg(query.numRowsAffected())); } // Mark first and last showings if (grab_data) { MSqlQuery updt(MSqlQuery::InitCon()); updt.prepare("UPDATE program SET first = 0, last = 0;"); if (!updt.exec()) MythDB::DBError("Clearing first and last showings", updt); VERBOSE(VB_GENERAL, "Marking episode first showings."); MSqlQuery query(MSqlQuery::InitCon()); query.prepare("SELECT MIN(starttime),programid FROM program " "WHERE programid > '' GROUP BY programid;"); if (query.exec()) { while(query.next()) { updt.prepare("UPDATE program set first = 1 " "WHERE starttime = :STARTTIME " " AND programid = :PROGRAMID;"); updt.bindValue(":STARTTIME", query.value(0).toDateTime()); updt.bindValue(":PROGRAMID", query.value(1).toString()); if (!updt.exec()) MythDB::DBError("Marking first showings by id", updt); } } int found = query.size(); query.prepare("SELECT MIN(starttime),title,subtitle,description " "FROM program WHERE programid = '' " "GROUP BY title,subtitle,description;"); if (query.exec()) { while(query.next()) { updt.prepare("UPDATE program set first = 1 " "WHERE starttime = :STARTTIME " " AND title = :TITLE " " AND subtitle = :SUBTITLE " " AND description = :DESCRIPTION"); updt.bindValue(":STARTTIME", query.value(0).toDateTime()); updt.bindValue(":TITLE", query.value(1).toString()); updt.bindValue(":SUBTITLE", query.value(2).toString()); updt.bindValue(":DESCRIPTION", query.value(3).toString()); if (!updt.exec()) MythDB::DBError("Marking first showings", updt); } } found += query.size(); VERBOSE(VB_GENERAL, QString(" Found %1").arg(found)); VERBOSE(VB_GENERAL, "Marking episode last showings."); query.prepare("SELECT MAX(starttime),programid FROM program " "WHERE programid > '' GROUP BY programid;"); if (query.exec()) { while(query.next()) { updt.prepare("UPDATE program set last = 1 " "WHERE starttime = :STARTTIME " " AND programid = :PROGRAMID;"); updt.bindValue(":STARTTIME", query.value(0).toDateTime()); updt.bindValue(":PROGRAMID", query.value(1).toString()); if (!updt.exec()) MythDB::DBError("Marking last showings by id", updt); } } found = query.size(); query.prepare("SELECT MAX(starttime),title,subtitle,description " "FROM program WHERE programid = '' " "GROUP BY title,subtitle,description;"); if (query.exec()) { while(query.next()) { updt.prepare("UPDATE program set last = 1 " "WHERE starttime = :STARTTIME " " AND title = :TITLE " " AND subtitle = :SUBTITLE " " AND description = :DESCRIPTION"); updt.bindValue(":STARTTIME", query.value(0).toDateTime()); updt.bindValue(":TITLE", query.value(1).toString()); updt.bindValue(":SUBTITLE", query.value(2).toString()); updt.bindValue(":DESCRIPTION", query.value(3).toString()); if (!updt.exec()) MythDB::DBError("Marking last showings", updt); } } found += query.size(); VERBOSE(VB_GENERAL, QString(" Found %1").arg(found)); } if (1) // limit MSqlQuery's lifetime { MSqlQuery query(MSqlQuery::InitCon()); query.prepare("SELECT count(previouslyshown) " "FROM program WHERE previouslyshown = 1;"); if (query.exec() && query.next()) { if (query.value(0).toInt() != 0) { query.prepare("UPDATE settings SET data = '1' " "WHERE value = 'HaveRepeats';"); if (!query.exec()) MythDB::DBError("Setting HaveRepeats", query); } else { query.prepare("UPDATE settings SET data = '0' " "WHERE value = 'HaveRepeats';"); if (!query.exec()) MythDB::DBError("Clearing HaveRepeats", query); } } } if ((usingDataDirect) && (gCoreContext->GetNumSetting("MythFillGrabberSuggestsTime", 1))) { fill_data.ddprocessor.GrabNextSuggestedTime(); } VERBOSE(VB_GENERAL, "\n" "===============================================================\n" "| Attempting to contact the master backend for rescheduling. |\n" "| If the master is not running, rescheduling will happen when |\n" "| the master backend is restarted. |\n" "==============================================================="); if (grab_data || mark_repeats) ScheduledRecording::signalChange(-1); RemoteSendMessage("CLEAR_SETTINGS_CACHE"); SendMythSystemEvent("MYTHFILLDATABASE_RAN"); VERBOSE(VB_IMPORTANT, "mythfilldatabase run complete."); return FILLDB_EXIT_OK; }
bool AcquireImages() { // Create a GEV Device finder dialog PvDeviceFinderWnd lDeviceFinderWnd; // Prompt the user to select a GEV Device lDeviceFinderWnd.ShowModal(); // Get the connectivity information for the selected GEV Device PvDeviceInfo* lDeviceInfo = lDeviceFinderWnd.GetSelected(); // If no device is selected, abort if( lDeviceInfo == NULL ) { cout << "No device selected." << endl; return false; } PvString lMACAddress = lDeviceInfo->GetMACAddress(); PvString lIPAddress = lDeviceInfo->GetIPAddress(); // Connect to the GEV Device PvDevice lDevice; cout << "Connecting to " << lMACAddress.GetAscii() << endl; // if ( !lDevice.Connect( lDeviceInfo ).IsOK() ) if ( !lDevice.Connect( lDeviceInfo ).IsOK() ) { cout << "Unable to connect to " << lMACAddress.GetAscii() << endl; return false; } cout << "Successfully connected to " << lMACAddress.GetAscii() << endl; cout << endl; SourceList lSources; // Get source selector PvGenEnum *lSourceSelector = lDevice.GetGenParameters()->GetEnum( "SourceSelector" ); if ( lSourceSelector != NULL ) { // Go through all sources, create source objects PvInt64 lCount = 0; lSourceSelector->GetEntriesCount( lCount ); for ( PvInt64 i = 0; i < lCount; i++ ) { // Get source enum entry const PvGenEnumEntry *lEE = NULL; lSourceSelector->GetEntryByIndex( i, &lEE ); // If available, create source if ( ( lEE != NULL ) && lEE->IsAvailable() ) { // Get source name PvString lSourceName; lEE->GetName( lSourceName ); // Create source Source *lSource = new Source( &lDevice, lIPAddress, lSourceName ); lSource->Open(); // Add to sources list lSources.push_back( lSource ); cout << endl; } } } else { // If no source selector, just create a single source Source *lSource = new Source( &lDevice, lIPAddress, "" ); lSource->Open(); // Add to sources list lSources.push_back( lSource ); cout << endl; } // Start the acquisiton on all sources SourceList::iterator lIt = lSources.begin(); while ( lIt != lSources.end() ) { ( *( lIt++ ) )->StartAcquisition(); cout << endl; } // Aggressive initial value, will be adjusted vs frame rate PvUInt32 lTimeout = 1; // Acquire images until the user instructs us to stop cout << "<press a key to stop streaming>" << endl; while ( !PvKbHit() ) { double lNewTimeout = 1000.0; lIt = lSources.begin(); while ( lIt != lSources.end() ) { ( *lIt )->RetrieveImages( lTimeout ); ( *lIt )->PrintStatistics(); // Always use the smallest recommended timeout double lRecommendedTimeout = ( *lIt )->GetRecommendedTimeout(); if ( lRecommendedTimeout < lNewTimeout ) { lNewTimeout = lRecommendedTimeout; } lIt++; } // Update timeout for next round - smallest recommended divided by number of sources lTimeout = static_cast<PvUInt32>( lNewTimeout / static_cast<double>( lSources.size() ) + 0.5 ); cout << "\r"; } PvGetChar(); // Flush key buffer for next stop cout << endl << endl; // Stop the acquisiton on all sources lIt = lSources.begin(); while ( lIt != lSources.end() ) { ( *( lIt++ ) )->StopAcquisition(); cout << endl; } // Close and delete sources lIt = lSources.begin(); while ( lIt != lSources.end() ) { ( *lIt )->Close(); cout << endl; delete *lIt; lIt++; } // Finally disconnect the device. Optional, still nice to have cout << "Disconnecting device" << endl; lDevice.Disconnect(); return true; }
void CSourceSaver::SaveSources(CPartFile* file, SourceList* prevsources, LPCTSTR slsfile, UINT maxSourcesToSave) { SourceList srcstosave; CSourceData* sourcedata; ASSERT(srcstosave.IsEmpty()); POSITION pos2,pos; CUpDownClient* cur_src; // Choose best sources for the file for(pos = file->srclist.GetHeadPosition();pos!=0;){ cur_src = file->srclist.GetNext(pos); if (cur_src->GetDownloadState() != DS_ONQUEUE && cur_src->GetDownloadState() != DS_DOWNLOADING && cur_src->GetDownloadState() != DS_NONEEDEDPARTS || cur_src->IsEd2kClient() == false) continue; if (srcstosave.IsEmpty()) { sourcedata = new CSourceData(cur_src, CalcExpiration(EXPIREIN)); srcstosave.AddHead(sourcedata); continue; } // Skip also Required Obfuscation, because we don't save the userhash (and we don't know if all settings are still valid on next restart) if (cur_src->RequiresCryptLayer() ||thePrefs.IsClientCryptLayerRequired()) continue; if ((UINT)srcstosave.GetCount() < maxSourcesToSave || (cur_src->GetAvailablePartCount() > srcstosave.GetTail()->partsavailable) || (cur_src->GetSourceExchange1Version() > srcstosave.GetTail()->nSrcExchangeVer)) { if ((UINT)srcstosave.GetCount() == maxSourcesToSave) delete srcstosave.RemoveTail(); ASSERT((UINT)srcstosave.GetCount() < maxSourcesToSave); bool bInserted = false; for (pos2 = srcstosave.GetTailPosition();pos2 != 0;srcstosave.GetPrev(pos2)){ CSourceData* cur_srctosave = srcstosave.GetAt(pos2); // khaos::kmod+ Source Exchange Version if (file->GetAvailableSrcCount() > (maxSourcesToSave*2) && cur_srctosave->nSrcExchangeVer > cur_src->GetSourceExchange1Version()) { bInserted = true; } else if (file->GetAvailableSrcCount() > (maxSourcesToSave*2) && cur_srctosave->nSrcExchangeVer == cur_src->GetSourceExchange1Version() && cur_srctosave->partsavailable > cur_src->GetAvailablePartCount()) { bInserted = true; } else if (file->GetAvailableSrcCount() <= (maxSourcesToSave*2) && cur_srctosave->partsavailable > cur_src->GetAvailablePartCount()) { bInserted = true; } const uint8* srcstatus = cur_src->GetPartStatus(); if (srcstatus){ if (cur_src->GetPartCount() == file->GetPartCount()){ // only save sources which have needed parts for (uint16 x = 0; x < file->GetPartCount(); x++){ //MORPH - Changed by SiRoB, ICS merged into partstatus /* if (srcstatus[x] && !file->IsPartShareable(x)){ */ if ((srcstatus[x]&SC_AVAILABLE) && !file->IsPartShareable(x)){ bInserted = true; break; } } } } if (bInserted) { sourcedata = new CSourceData(cur_src, CalcExpiration(EXPIREIN)); srcstosave.InsertAfter(pos2, sourcedata); break; } // khaos::kmod- } if (!bInserted) { sourcedata = new CSourceData(cur_src, CalcExpiration(EXPIREIN)); srcstosave.AddHead(sourcedata); } } } // Add previously saved sources if found sources does not reach the limit for (pos = prevsources->GetHeadPosition(); pos; prevsources->GetNext(pos)) { CSourceData* cur_sourcedata = prevsources->GetAt(pos); if ((UINT)srcstosave.GetCount() == maxSourcesToSave) break; ASSERT((UINT)srcstosave.GetCount() <= maxSourcesToSave); bool bFound = false; for (pos2 = srcstosave.GetHeadPosition(); pos2; srcstosave.GetNext(pos2)) { if (srcstosave.GetAt(pos2)->Compare(cur_sourcedata)) { bFound = true; break; } } if (!bFound) { srcstosave.AddTail(new CSourceData(cur_sourcedata)); } } //DEBUG_ONLY(AddLogLine(/*TBN_NONOTIFY, */false, "Saving %i sources for file %s", srcstosave.GetCount(), file->GetFileName())); CString strLine; CStdioFile f; if (!f.Open(slsfile, CFile::modeCreate | CFile::modeWrite | CFile::typeText)) return; f.WriteString(_T("#format: a.b.c.d:port,expirationdate(yymmddhhmm);\r\n")); f.WriteString(_T("#") + file->GetED2kLink() + _T("\r\n")); //MORPH - Added by IceCream, Storing ED2K link in Save Source files, To recover corrupted met by skynetman while (!srcstosave.IsEmpty()) { CSourceData* cur_src = srcstosave.RemoveHead(); uint32 dwID = cur_src->sourceID; uint16 wPort = cur_src->sourcePort; uint32 dwserverip = cur_src->serverip; uint16 wserverport = cur_src->serverport; strLine.Format(_T("%s:%i,%s,%i,%s:%i;\r\n"), ipstr(dwID), wPort, cur_src->expiration, cur_src->nSrcExchangeVer, ipstr(dwserverip), wserverport); delete cur_src; f.WriteString(strLine); } f.Close(); }
// Watch current set of sources and process events void XmlRpcDispatch::work(double timeout_in_seconds) { // Compute end time _endTime = (timeout_in_seconds < 0.0) ? -1.0 : (getTime() + timeout_in_seconds); _doClear = false; _inWork = true; // Only work while there is something to monitor while (_sources.size() > 0) { // // Construct the sets of descriptors we are interested in // fd_set inFd, outFd, excFd; // FD_ZERO(&inFd); // FD_ZERO(&outFd); // FD_ZERO(&excFd); // int maxFd = -1; // Not used on windows // SourceList::iterator it; int fds_size = _sources.size(); std::vector<struct pollfd> fds(fds_size); { int __offset = 0; for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it) { fds[__offset].fd = it->getSource()->getfd(); fds[__offset].events = 0; fds[__offset].revents = 0; if (it->getMask() & ReadableEvent) fds[__offset].events |= POLLIN; if (it->getMask() & WritableEvent) fds[__offset].events |= POLLOUT; if (it->getMask() & Exception) fds[__offset].events |= POLLERR; // 2 if (it->getMask() && fd > maxFd) maxFd = fd; ++__offset; } } // Check for events returnhereoninterruptedsyscall: int nEvents; if (timeout_in_seconds < 0.0) nEvents = poll(&fds[0], fds_size, -1); else { nEvents = poll(&fds[0],fds_size, timeout_in_seconds * 1000); } if(nEvents == -1 and errno == EINTR) goto returnhereoninterruptedsyscall; if (nEvents < 0) { LOG_ERROR("Error in XmlRpcDispatch::work: error in select " << strerror(errno)); // LOG_ERROR(strerror(errno)); // XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents); _inWork = false; return; } // Process events { size_t __offset = 0; for (SourceList::iterator it = _sources.begin(); it != _sources.end(); ) { SourceList::iterator thisIt = it++; XmlRpcSource* src = thisIt->getSource(); unsigned newMask = (unsigned) -1; // accepting a new connection (XmlRpcServer::handleEvent) // will add a new entry to _sources but we don't have an // entry in the fds around. if (__offset < fds.size()) { assert(fds[__offset].fd == src->getfd()); // if (fd <= maxFd) // { // If you select on multiple event types this could be ambiguous if (fds[__offset].revents bitand POLLIN) { newMask &= src->handleEvent(ReadableEvent); } if (fds[__offset].revents bitand POLLOUT) { newMask &= src->handleEvent(WritableEvent); } if (fds[__offset].revents bitand POLLERR) { newMask &= src->handleEvent(Exception); } } if (newMask == 0) { _sources.erase(thisIt); // Stop monitoring this one if (!src->getKeepOpen()) { src->close(); } } else if (newMask != (unsigned) -1) { thisIt->getMask() = newMask; } __offset++; } } // Check whether to clear all sources if (_doClear) { SourceList closeList = _sources; _sources.clear(); for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) { XmlRpcSource *src = it->getSource(); src->close(); } _doClear = false; } // Check whether end time has passed if (0 <= _endTime && getTime() > _endTime) break; } _inWork = false; }