From 67dbb2973f32ccf52c0e5f3e2b5848320a215062 Mon Sep 17 00:00:00 2001 From: Andreas Monzner Date: Mon, 11 Aug 2008 22:02:24 +0000 Subject: [PATCH 1/1] some service scan improovements - add a only free scan - the scan now finds also services not listed in SDT - add option "clear before scan" also for single transponder searches For the only free scan a change in the main lamedb transponder format was needed... i think this breaks some external settings editors To detect the service format now the service database file starts with "eDVB services /4/" .. the old format was "eDVB services /3/" .. e2 can read the old and the new format.. but it writes always the new format! --- lib/components/scan.h | 3 +- lib/dvb/db.cpp | 89 +++++-- lib/dvb/db.h | 1 + lib/dvb/frontend.cpp | 3 +- lib/dvb/frontend.h | 4 + lib/dvb/idvb.h | 3 + lib/dvb/scan.cpp | 459 ++++++++++++++++++++++++++------ lib/dvb/scan.h | 32 ++- lib/python/Screens/ScanSetup.py | 57 ++-- 9 files changed, 504 insertions(+), 147 deletions(-) diff --git a/lib/components/scan.h b/lib/components/scan.h index 3d8984e1..222158bc 100644 --- a/lib/components/scan.h +++ b/lib/components/scan.h @@ -44,7 +44,8 @@ public: void addInitial(const eDVBFrontendParametersTerrestrial &p); /* please keep the flags in sync with lib/dvb/scan.h ! */ - enum { scanNetworkSearch=1, scanRemoveServices=4, scanDontRemoveFeeds=8, clearToScanOnFirstNIT = 16 }; + enum { scanNetworkSearch=1, scanRemoveServices=4, scanDontRemoveFeeds=8, scanDontRemoveUnscanned=16, clearToScanOnFirstNIT = 32, scanOnlyFree = 64 }; + int start(int feid, int flags=0 ); SWIG_VOID(RESULT) getFrontend(ePtr &SWIG_OUTPUT); SWIG_VOID(RESULT) getCurrentTransponder(ePtr &SWIG_OUTPUT); diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index 9035b8f0..02ecc1d2 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -284,13 +284,14 @@ void eDVBDB::loadServicelist(const char *file) return; } char line[256]; - if ((!fgets(line, 256, f)) || strncmp(line, "eDVB services", 13)) + int version=3; + if ((!fgets(line, 256, f)) || sscanf(line, "eDVB services /%d/", &version) != 1) { - eDebug("not a servicefile"); + eDebug("not a valid servicefile"); fclose(f); return; } - eDebug("reading services"); + eDebug("reading services (version %d)", version); if ((!fgets(line, 256, f)) || strcmp(line, "transponders\n")) { eDebug("services invalid, no transponders"); @@ -325,11 +326,15 @@ void eDVBDB::loadServicelist(const char *file) { eDVBFrontendParametersSatellite sat; int frequency, symbol_rate, polarisation, fec, orbital_position, inversion, + flags=0, system=eDVBFrontendParametersSatellite::System::DVB_S, modulation=eDVBFrontendParametersSatellite::Modulation::QPSK, rolloff=eDVBFrontendParametersSatellite::RollOff::alpha_0_35, pilot=eDVBFrontendParametersSatellite::Pilot::Unknown; - sscanf(line+3, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &polarisation, &fec, &orbital_position, &inversion, &system, &modulation, &rolloff, &pilot); + if (version == 3) + sscanf(line+3, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &polarisation, &fec, &orbital_position, &inversion, &system, &modulation, &rolloff, &pilot); + else + sscanf(line+3, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &polarisation, &fec, &orbital_position, &inversion, &flags, &system, &modulation, &rolloff, &pilot); sat.frequency = frequency; sat.symbol_rate = symbol_rate; sat.polarisation = polarisation; @@ -342,11 +347,12 @@ void eDVBDB::loadServicelist(const char *file) sat.rolloff = rolloff; sat.pilot = pilot; feparm->setDVBS(sat); + feparm->setFlags(flags); } else if (line[1]=='t') { eDVBFrontendParametersTerrestrial ter; - int frequency, bandwidth, code_rate_HP, code_rate_LP, modulation, transmission_mode, guard_interval, hierarchy, inversion; - sscanf(line+3, "%d:%d:%d:%d:%d:%d:%d:%d:%d", &frequency, &bandwidth, &code_rate_HP, &code_rate_LP, &modulation, &transmission_mode, &guard_interval, &hierarchy, &inversion); + int frequency, bandwidth, code_rate_HP, code_rate_LP, modulation, transmission_mode, guard_interval, hierarchy, inversion, flags=0; + sscanf(line+3, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", &frequency, &bandwidth, &code_rate_HP, &code_rate_LP, &modulation, &transmission_mode, &guard_interval, &hierarchy, &inversion, &flags); ter.frequency = frequency; ter.bandwidth = bandwidth; ter.code_rate_HP = code_rate_HP; @@ -357,20 +363,23 @@ void eDVBDB::loadServicelist(const char *file) ter.hierarchy = hierarchy; ter.inversion = inversion; feparm->setDVBT(ter); + feparm->setFlags(flags); } else if (line[1]=='c') { eDVBFrontendParametersCable cab; int frequency, symbol_rate, inversion=eDVBFrontendParametersCable::Inversion::Unknown, modulation=eDVBFrontendParametersCable::Modulation::Auto, - fec_inner=eDVBFrontendParametersCable::FEC::fAuto; - sscanf(line+3, "%d:%d:%d:%d:%d", &frequency, &symbol_rate, &inversion, &modulation, &fec_inner); + fec_inner=eDVBFrontendParametersCable::FEC::fAuto, + flags=0; + sscanf(line+3, "%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &inversion, &modulation, &fec_inner, &flags); cab.frequency = frequency; cab.fec_inner = fec_inner; cab.inversion = inversion; cab.symbol_rate = symbol_rate; cab.modulation = modulation; feparm->setDVBC(cab); + feparm->setFlags(flags); } } addChannelToList(channelid, feparm); @@ -469,7 +478,7 @@ void eDVBDB::saveServicelist(const char *file) int channels=0, services=0; if (!f) eFatal("couldn't save lame channel db!"); - fprintf(f, "eDVB services /3/\n"); + fprintf(f, "eDVB services /4/\n"); fprintf(f, "transponders\n"); for (std::map::const_iterator i(m_channels.begin()); i != m_channels.end(); ++i) @@ -482,15 +491,18 @@ void eDVBDB::saveServicelist(const char *file) eDVBFrontendParametersSatellite sat; eDVBFrontendParametersTerrestrial ter; eDVBFrontendParametersCable cab; + unsigned int flags; // flagOnlyFree yet.. + ch.m_frontendParameters->getFlags(flags); if (!ch.m_frontendParameters->getDVBS(sat)) { if (sat.system == eDVBFrontendParametersSatellite::System::DVB_S2) { - fprintf(f, "\ts %d:%d:%d:%d:%d:%d:%d:%d:%d", + fprintf(f, "\ts %d:%d:%d:%d:%d:%d:%d:%d:%d:%d", sat.frequency, sat.symbol_rate, sat.polarisation, sat.fec, sat.orbital_position > 1800 ? sat.orbital_position - 3600 : sat.orbital_position, sat.inversion, + flags, sat.system, sat.modulation, sat.rolloff); @@ -501,24 +513,24 @@ void eDVBDB::saveServicelist(const char *file) } else { - fprintf(f, "\ts %d:%d:%d:%d:%d:%d\n", + fprintf(f, "\ts %d:%d:%d:%d:%d:%d:%d\n", sat.frequency, sat.symbol_rate, sat.polarisation, sat.fec, sat.orbital_position > 1800 ? sat.orbital_position - 3600 : sat.orbital_position, - sat.inversion); + sat.inversion, flags); } } else if (!ch.m_frontendParameters->getDVBT(ter)) { - fprintf(f, "\tt %d:%d:%d:%d:%d:%d:%d:%d:%d\n", + fprintf(f, "\tt %d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n", ter.frequency, ter.bandwidth, ter.code_rate_HP, ter.code_rate_LP, ter.modulation, ter.transmission_mode, - ter.guard_interval, ter.hierarchy, ter.inversion); + ter.guard_interval, ter.hierarchy, ter.inversion, flags); } else if (!ch.m_frontendParameters->getDVBC(cab)) { - fprintf(f, "\tc %d:%d:%d:%d:%d\n", - cab.frequency, cab.symbol_rate, cab.inversion, cab.modulation, cab.fec_inner); + fprintf(f, "\tc %d:%d:%d:%d:%d:%d\n", + cab.frequency, cab.symbol_rate, cab.inversion, cab.modulation, cab.fec_inner, flags); } fprintf(f, "/\n"); channels++; @@ -1228,6 +1240,45 @@ RESULT eDVBDB::removeServices(eDVBChannelID chid, unsigned int orbpos) return ret; } +RESULT eDVBDB::removeServices(iDVBFrontendParameters *feparm) +{ + int ret = -1; + std::set removed_chids; + std::map::iterator it(m_channels.begin()); + while (it != m_channels.end()) + { + int diff; + if (!feparm->calculateDifference(&(*it->second.m_frontendParameters), diff, false)) + { + if (diff < 4000) + { + removed_chids.insert(it->first); + m_channels.erase(it++); + } + else + ++it; + } + else + ++it; + } + if (!removed_chids.empty()) + { + std::map >::iterator service(m_services.begin()); + while(service != m_services.end()) + { + eDVBChannelID chid; + service->first.getChannelID(chid); + std::set::iterator it(removed_chids.find(chid)); + if (it != removed_chids.end()) + m_services.erase(service++); + else + ++service; + } + ret = 0; + } + return ret; +} + RESULT eDVBDB::addFlag(const eServiceReference &ref, unsigned int flagmask) { if (ref.type == eServiceReference::idDVB) @@ -1315,9 +1366,13 @@ RESULT eDVBDB::removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned i RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm) { channel ch; + std::map::iterator it = m_channels.find(id); assert(feparm); ch.m_frontendParameters = feparm; - m_channels.insert(std::pair(id, ch)); + if (it != m_channels.end()) + it->second = ch; + else + m_channels.insert(std::pair(id, ch)); return 0; } diff --git a/lib/dvb/db.h b/lib/dvb/db.h index 512f81e4..55e008fb 100644 --- a/lib/dvb/db.h +++ b/lib/dvb/db.h @@ -44,6 +44,7 @@ public: #ifndef SWIG RESULT removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned int orb_pos); RESULT removeServices(eDVBChannelID chid, unsigned int orb_pos); + RESULT removeServices(iDVBFrontendParameters *feparm); RESULT addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm); RESULT removeChannel(const eDVBChannelID &id); diff --git a/lib/dvb/frontend.cpp b/lib/dvb/frontend.cpp index 2d38dc25..d7bc6737 100644 --- a/lib/dvb/frontend.cpp +++ b/lib/dvb/frontend.cpp @@ -204,7 +204,8 @@ void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescr guard_interval, hierarchy, modulation); } -eDVBFrontendParameters::eDVBFrontendParameters(): m_type(-1) +eDVBFrontendParameters::eDVBFrontendParameters() + :m_type(-1), m_flags(0) { } diff --git a/lib/dvb/frontend.h b/lib/dvb/frontend.h index 49e2da89..cbe3dfc2 100644 --- a/lib/dvb/frontend.h +++ b/lib/dvb/frontend.h @@ -13,6 +13,7 @@ class eDVBFrontendParameters: public iDVBFrontendParameters eDVBFrontendParametersTerrestrial terrestrial; }; int m_type; + int m_flags; public: eDVBFrontendParameters(); ~eDVBFrontendParameters() @@ -32,6 +33,9 @@ public: RESULT getHash(unsigned long &) const; RESULT calcLockTimeout(unsigned int &) const; + + RESULT getFlags(unsigned int &flags) const { flags = m_flags; return 0; } + RESULT setFlags(unsigned int flags) { m_flags = flags; return 0; } }; #ifndef SWIG diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index cd3e0ec5..ebf22374 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -375,6 +375,7 @@ public: virtual RESULT removeService(const eServiceReference &service)=0; virtual RESULT removeServices(eDVBChannelID chid=eDVBChannelID(), unsigned int orb_pos=0xFFFFFFFF)=0; virtual RESULT removeServices(int dvb_namespace=-1, int tsid=-1, int onid=-1, unsigned int orb_pos=0xFFFFFFFF)=0; + virtual RESULT removeServices(iDVBFrontendParameters *feparm)=0; virtual RESULT addFlag(const eServiceReference &service, unsigned int flagmask=0xFFFFFFFF)=0; virtual RESULT removeFlag(const eServiceReference &service, unsigned int flagmask=0xFFFFFFFF)=0; virtual RESULT removeFlags(unsigned int flagmask, eDVBChannelID chid=eDVBChannelID(), unsigned int orb_pos=0xFFFFFFFF)=0; @@ -402,6 +403,7 @@ class iDVBFrontendParameters: public iObject ~iDVBFrontendParameters(); #endif public: + enum { flagOnlyFree = 1 }; virtual RESULT getSystem(int &SWIG_OUTPUT) const = 0; virtual RESULT getDVBS(eDVBFrontendParametersSatellite &SWIG_OUTPUT) const = 0; virtual RESULT getDVBC(eDVBFrontendParametersCable &SWIG_OUTPUT) const = 0; @@ -410,6 +412,7 @@ public: virtual RESULT calculateDifference(const iDVBFrontendParameters *parm, int &SWIG_OUTPUT, bool exact) const = 0; virtual RESULT getHash(unsigned long &SWIG_OUTPUT) const = 0; virtual RESULT calcLockTimeout(unsigned int &) const = 0; + virtual RESULT getFlags(unsigned int &) const = 0; }; SWIG_TEMPLATE_TYPEDEF(ePtr, iDVBFrontendParametersPtr); diff --git a/lib/dvb/scan.cpp b/lib/dvb/scan.cpp index 8d412ce7..3c4f407b 100644 --- a/lib/dvb/scan.cpp +++ b/lib/dvb/scan.cpp @@ -22,7 +22,7 @@ DEFINE_REF(eDVBScan); eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug) :m_channel(channel), m_channel_state(iDVBChannel::state_idle) ,m_ready(0), m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT) - ,m_flags(0), m_usePAT(usePAT) + ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0), m_usePAT(usePAT) { scan_debug=debug; if (m_channel->getDemux(m_demux)) @@ -84,10 +84,12 @@ RESULT eDVBScan::nextChannel() { ePtr fe; - m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0; + m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0; m_ready = 0; + m_pat_tsid = eTransportStreamID(); + /* check what we need */ m_ready_all = readySDT; @@ -152,6 +154,17 @@ RESULT eDVBScan::startFilter() m_PAT->getSections().begin(); assert(i != m_PAT->getSections().end()); tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id + m_pat_tsid = eTransportStreamID(tsid); + for (; i != m_PAT->getSections().end(); ++i) + { + const ProgramAssociationSection &pat = **i; + ProgramAssociationConstIterator program = pat.getPrograms()->begin(); + for (; program != pat.getPrograms()->end(); ++program) + m_pmts_to_read.insert(std::pair((*program)->getProgramNumber(), service((*program)->getProgramMapPid()))); + } + m_PMT = new eTable(); + CONNECT(m_PMT->tableReady, eDVBScan::PMTready); + PMTready(-1); // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different { @@ -212,7 +225,7 @@ RESULT eDVBScan::startFilter() void eDVBScan::SDTready(int err) { - SCAN_eDebug("got sdt"); + SCAN_eDebug("got sdt %d", err); m_ready |= readySDT; if (!err) m_ready |= validSDT; @@ -246,6 +259,122 @@ void eDVBScan::PATready(int err) startFilter(); // for starting the SDT filter } +void eDVBScan::PMTready(int err) +{ + SCAN_eDebug("got pmt %d", err); + if (!err) + { + bool scrambled = false; + bool have_audio = false; + bool have_video = false; + unsigned short pcrpid = 0xFFFF; + std::vector::const_iterator i; + for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i) + { + const ProgramMapSection &pmt = **i; + if (pcrpid == 0xFFFF) + pcrpid = pmt.getPcrPid(); + else + eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid()); + ElementaryStreamInfoConstIterator es; + for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es) + { + int isaudio = 0, isvideo = 0, is_scrambled = 0; + switch ((*es)->getType()) + { + case 0x1b: // AVC Video Stream (MPEG4 H264) + case 0x01: // MPEG 1 video + case 0x02: // MPEG 2 video + isvideo = 1; + //break; fall through !!! + case 0x03: // MPEG 1 audio + case 0x04: // MPEG 2 audio: + if (!isvideo) + isaudio = 1; + //break; fall through !!! + case 0x06: // PES Private + case 0x81: // user private + /* PES private can contain AC-3, DTS or lots of other stuff. + check descriptors to get the exact type. */ + for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); + desc != (*es)->getDescriptors()->end(); ++desc) + { + switch ((*desc)->getTag()) + { + case DTS_DESCRIPTOR: + case AAC_DESCRIPTOR: + isaudio = 1; + case AC3_DESCRIPTOR: + isaudio = 1; + break; + case CA_DESCRIPTOR: + is_scrambled = 1; + break; + case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */ + { + /* libdvbsi++ doesn't yet support this descriptor type, so work around. */ + if ((*desc)->getLength() != 4) + break; + unsigned char descr[6]; + (*desc)->writeToBuffer(descr); + int format_identifier = (descr[2] << 24) | (descr[3] << 16) | (descr[4] << 8) | (descr[5]); + switch (format_identifier) + { + case 0x41432d33: + isaudio = 1; + default: + break; + } + break; + } + } + } + break; + } + if (isaudio) + have_audio = true; + else if (isvideo) + have_video = true; + else + continue; + if (is_scrambled) + scrambled = true; + } + for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); + desc != pmt.getDescriptors()->end(); ++desc) + { + if ((*desc)->getTag() == CA_DESCRIPTOR) + scrambled = true; + } + } + m_pmt_in_progress->second.scrambled = scrambled; + if ( have_video ) + m_pmt_in_progress->second.serviceType = 1; + else if ( have_audio ) + m_pmt_in_progress->second.serviceType = 2; + else + m_pmt_in_progress->second.serviceType = 100; + } + if (err == -2) // aborted in sdt progress + m_pmts_to_read.erase(m_pmt_in_progress++); + else if (m_pmt_running) + ++m_pmt_in_progress; + else + { + m_pmt_in_progress = m_pmts_to_read.begin(); + m_pmt_running = true; + } + + if (m_pmt_in_progress != m_pmts_to_read.end()) + m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first)); + else + { + m_pmt_running = false; + channelDone(); + } +} + + void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm) { /* add it to the list of known channels. */ @@ -357,13 +486,19 @@ int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *c void eDVBScan::channelDone() { - if (m_ready & validSDT) + if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running)) { unsigned long hash = 0; // m_ch_current is not set, when eDVBScan is just used for a SDT update if (!m_ch_current) + { + unsigned int channelFlags; m_channel->getCurrentFrontendParameters(m_ch_current); + m_ch_current->getFlags(channelFlags); + if (channelFlags & iDVBFrontendParameters::flagOnlyFree) + m_flags |= scanOnlyFree; + } m_ch_current->getHash(hash); @@ -381,6 +516,7 @@ void eDVBScan::channelDone() if (m_ready & validNIT) { + eDebug("validNIT"); int system; std::list > m_ch_toScan_backup; m_ch_current->getSystem(system); @@ -512,9 +648,17 @@ void eDVBScan::channelDone() } m_ready &= ~validNIT; } - - if ((m_ready & m_ready_all) != m_ready_all) + + if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all) + { + if (m_abort_current_pmt) + { + m_abort_current_pmt = false; + PMTready(-1); + } return; + } + SCAN_eDebug("channel done!"); /* if we had services on this channel, we declare @@ -537,7 +681,106 @@ void eDVBScan::channelDone() These are the reasons for adding the transponder here, and not before. */ - + + for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();) + { + int type; + eServiceReferenceDVB ref; + ePtr service = new eDVBService; + + if (!m_chid_current) + { + unsigned long hash = 0; + + // m_ch_current is not set, when eDVBScan is just used for a SDT update + if (!m_ch_current) + { + unsigned int channelFlags; + m_channel->getCurrentFrontendParameters(m_ch_current); + m_ch_current->getFlags(channelFlags); + if (channelFlags & iDVBFrontendParameters::flagOnlyFree) + m_flags |= scanOnlyFree; + } + + m_ch_current->getHash(hash); + + m_chid_current = eDVBChannelID( + buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash), + m_pat_tsid, eOriginalNetworkID(0)); + } + + if (m_pmt_in_progress->second.serviceType == 1) + SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first); + else if (m_pmt_in_progress->second.serviceType == 2) + SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first); + else + SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first); + + ref.set(m_chid_current); + ref.setServiceID(m_pmt_in_progress->first); + ref.setServiceType(m_pmt_in_progress->second.serviceType); + + if (!m_ch_current->getSystem(type)) + { + char sname[255]; + char pname[255]; + memset(pname, 0, sizeof(pname)); + memset(sname, 0, sizeof(sname)); + switch(type) + { + case iDVBFrontend::feSatellite: + { + eDVBFrontendParametersSatellite parm; + m_ch_current->getDVBS(parm); + snprintf(sname, 255, "%d%c SID 0x%02x", + parm.frequency/1000, + parm.polarisation ? 'V' : 'H', + m_pmt_in_progress->first); + snprintf(pname, 255, "%s %s %d%c %d.%d°%c", + parm.system ? "DVB-S2" : "DVB-S", + parm.modulation == 1 ? "QPSK" : "8PSK", + parm.frequency/1000, + parm.polarisation ? 'V' : 'H', + parm.orbital_position/10, + parm.orbital_position%10, + parm.orbital_position > 0 ? 'E' : 'W'); + break; + } + case iDVBFrontend::feTerrestrial: + { + eDVBFrontendParametersTerrestrial parm; + m_ch_current->getDVBT(parm); + snprintf(sname, 255, "%d SID 0x%02x", + parm.frequency/1000, + m_pmt_in_progress->first); + break; + } + case iDVBFrontend::feCable: + { + eDVBFrontendParametersCable parm; + m_ch_current->getDVBC(parm); + snprintf(sname, 255, "%d SID 0x%02x", + parm.frequency/1000, + m_pmt_in_progress->first); + break; + } + } + SCAN_eDebug("name '%s', provider_name '%s'", sname, pname); + service->m_service_name = convertDVBUTF8(sname); + service->genSortName(); + service->m_provider_name = pname; + } + + std::pair >::iterator, bool> i = m_new_services.insert(std::pair >(ref, service)); + + if (i.second) + { + m_last_service = i.first; + m_event(evtNewService); + } + m_pmts_to_read.erase(m_pmt_in_progress++); + } + if (!m_chid_current) eWarning("SCAN: the current channel's ID was not corrected - not adding channel."); else @@ -598,52 +841,64 @@ void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags) std::list >::iterator it(m_ch_scanned.begin()); for (;it != m_ch_scanned.end(); ++it) { - int system; - (*it)->getSystem(system); - switch(system) + if (m_flags & scanDontRemoveUnscanned) { + eDebug("scanDontRemoveUnscanned!"); + db->removeServices(&(*(*it))); + } + else { - case iDVBFrontend::feSatellite: - { - eDVBFrontendParametersSatellite sat_parm; - (*it)->getDVBS(sat_parm); - scanned_sat_positions.insert(sat_parm.orbital_position); - break; - } - case iDVBFrontend::feTerrestrial: + int system; + (*it)->getSystem(system); + switch(system) { - clearTerrestrial=true; - break; - } - case iDVBFrontend::feCable: - { - clearCable=true; - break; + case iDVBFrontend::feSatellite: + { + eDVBFrontendParametersSatellite sat_parm; + (*it)->getDVBS(sat_parm); + scanned_sat_positions.insert(sat_parm.orbital_position); + break; + } + case iDVBFrontend::feTerrestrial: + { + clearTerrestrial=true; + break; + } + case iDVBFrontend::feCable: + { + clearCable=true; + break; + } } } } for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it) { - int system; - (*it)->getSystem(system); - switch(system) + if (m_flags & scanDontRemoveUnscanned) + db->removeServices(&(*(*it))); + else { - case iDVBFrontend::feSatellite: - { - eDVBFrontendParametersSatellite sat_parm; - (*it)->getDVBS(sat_parm); - scanned_sat_positions.insert(sat_parm.orbital_position); - break; - } - case iDVBFrontend::feTerrestrial: + int system; + (*it)->getSystem(system); + switch(system) { - clearTerrestrial=true; - break; - } - case iDVBFrontend::feCable: - { - clearCable=true; - break; + case iDVBFrontend::feSatellite: + { + eDVBFrontendParametersSatellite sat_parm; + (*it)->getDVBS(sat_parm); + scanned_sat_positions.insert(sat_parm.orbital_position); + break; + } + case iDVBFrontend::feTerrestrial: + { + clearTerrestrial=true; + break; + } + case iDVBFrontend::feCable: + { + clearCable=true; + break; + } } } } @@ -672,7 +927,15 @@ void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags) for (std::map >::const_iterator ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch) + { + if (m_flags & scanOnlyFree) + { + eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second); + ptr->setFlags(iDVBFrontendParameters::flagOnlyFree); + } db->addChannelToList(ch->first, ch->second); + } + for (std::map >::const_iterator service(m_new_services.begin()); service != m_new_services.end(); ++service) { @@ -712,61 +975,83 @@ RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescription for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s) { - SCAN_eDebugNoNewLine("SID %04x: ", (*s)->getServiceId()); + unsigned short service_id = (*s)->getServiceId(); + SCAN_eDebugNoNewLine("SID %04x: ", service_id); + bool add = true; - eServiceReferenceDVB ref; - ePtr service = new eDVBService; - - ref.set(chid); - ref.setServiceID((*s)->getServiceId()); - - for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin(); - desc != (*s)->getDescriptors()->end(); ++desc) - if ((*desc)->getTag() == SERVICE_DESCRIPTOR) - ref.setServiceType(((ServiceDescriptor&)**desc).getServiceType()); - - for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin(); - desc != (*s)->getDescriptors()->end(); ++desc) + if (m_flags & scanOnlyFree) { - switch ((*desc)->getTag()) - { - case SERVICE_DESCRIPTOR: + std::map::iterator it = + m_pmts_to_read.find(service_id); + if (it != m_pmts_to_read.end()) { - ServiceDescriptor &d = (ServiceDescriptor&)**desc; - service->m_service_name = convertDVBUTF8(d.getServiceName()); - service->genSortName(); - - service->m_provider_name = convertDVBUTF8(d.getServiceProviderName()); - SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str()); - break; + if (it->second.scrambled) + { + SCAN_eDebug("is scrambled!"); + add = false; + } } - case CA_IDENTIFIER_DESCRIPTOR: + else + SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!"); + } + + if (add) + { + eServiceReferenceDVB ref; + ePtr service = new eDVBService; + + ref.set(chid); + ref.setServiceID(service_id); + + for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin(); + desc != (*s)->getDescriptors()->end(); ++desc) { - CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc; - const CaSystemIdList &caids = *d.getCaSystemIds(); - SCAN_eDebugNoNewLine("CA "); - for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i) + switch ((*desc)->getTag()) + { + case SERVICE_DESCRIPTOR: + { + ServiceDescriptor &d = (ServiceDescriptor&)**desc; + ref.setServiceType(d.getServiceType()); + service->m_service_name = convertDVBUTF8(d.getServiceName()); + service->genSortName(); + + service->m_provider_name = convertDVBUTF8(d.getServiceProviderName()); + SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str()); + break; + } + case CA_IDENTIFIER_DESCRIPTOR: { - SCAN_eDebugNoNewLine("%04x ", *i); - service->m_ca.push_front(*i); + CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc; + const CaSystemIdList &caids = *d.getCaSystemIds(); + SCAN_eDebugNoNewLine("CA "); + for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i) + { + SCAN_eDebugNoNewLine("%04x ", *i); + service->m_ca.push_front(*i); + } + SCAN_eDebug(""); + break; + } + default: + SCAN_eDebug("descr<%x>", (*desc)->getTag()); + break; } - SCAN_eDebug(""); - break; } - default: - SCAN_eDebug("descr<%x>", (*desc)->getTag()); - break; + + std::pair >::iterator, bool> i = m_new_services.insert(std::pair >(ref, service)); + + if (i.second) + { + m_last_service = i.first; + m_event(evtNewService); } } - - std::pair >::iterator, bool> i = m_new_services.insert(std::pair >(ref, service)); - - if (i.second) - { - m_last_service = i.first; - m_event(evtNewService); - } + if (m_pmt_running && m_pmt_in_progress->first == service_id) + m_abort_current_pmt = true; + else + m_pmts_to_read.erase(service_id); } + return 0; } diff --git a/lib/dvb/scan.h b/lib/dvb/scan.h index 68e21a5d..50de21dc 100644 --- a/lib/dvb/scan.h +++ b/lib/dvb/scan.h @@ -5,10 +5,23 @@ #include #include #include +#include + #include #include #include +struct service +{ + service(unsigned short pmtPid) + :pmtPid(pmtPid), serviceType(0xFF), scrambled(false) + { + } + unsigned short pmtPid; + unsigned char serviceType; + bool scrambled; +}; + class eDVBScan: public Object, public iObject { DECLARE_REF(eDVBScan); @@ -41,21 +54,29 @@ class eDVBScan: public Object, public iObject std::map > m_new_channels; std::map > m_new_services; std::map >::iterator m_last_service; - + + std::map m_pmts_to_read; + std::map::iterator m_pmt_in_progress; + bool m_pmt_running; + bool m_abort_current_pmt; + std::list > m_ch_toScan, m_ch_scanned, m_ch_unavailable; ePtr m_ch_current; eDVBChannelID m_chid_current; - + eTransportStreamID m_pat_tsid; + ePtr > m_SDT; ePtr > m_NIT; ePtr > m_BAT; ePtr > m_PAT; - + ePtr > m_PMT; + void SDTready(int err); void NITready(int err); void BATready(int err); void PATready(int err); - + void PMTready(int err); + void addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm); void addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm); @@ -75,7 +96,8 @@ public: enum { scanNetworkSearch = 1, scanSearchBAT = 2, scanRemoveServices = 4, scanDontRemoveFeeds = 8, - clearToScanOnFirstNIT = 16 }; + scanDontRemoveUnscanned = 16, + clearToScanOnFirstNIT = 32, scanOnlyFree = 64 }; void start(const eSmartPtrList &known_transponders, int flags); diff --git a/lib/python/Screens/ScanSetup.py b/lib/python/Screens/ScanSetup.py index b14c7e74..35f482b4 100644 --- a/lib/python/Screens/ScanSetup.py +++ b/lib/python/Screens/ScanSetup.py @@ -400,12 +400,10 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): self.updateSatList() print self.scan_satselection[index_to_scan] self.list.append(getConfigListEntry(_("Satellite"), self.scan_satselection[index_to_scan])) - self.list.append(getConfigListEntry(_("Clear before scan"), self.scan_clearallservices)) + self.list.append(getConfigListEntry(_("Network scan"), self.scan_networkScan)) elif self.scan_type.value == "multisat": - # if (norotor) tlist = [] SatList = nimmanager.getSatListForNim(index_to_scan) - self.list.append(getConfigListEntry(_("Clear before scan"), self.scan_clearallservices)) for x in SatList: if self.Satexists(tlist, x[0]) == 0: tlist.append(x[0]) @@ -413,9 +411,6 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): configEntry = getConfigListEntry(nimmanager.getSatDescription(x[0]), sat) self.list.append(configEntry) self.multiscanlist.append((x[0], sat)) - # if (rotor): - # for sat in nimmanager.satList: - # self.list.append(getConfigListEntry(sat[1], self.scan_scansat[sat[0]])) elif nim.isCompatible("DVB-C"): if self.scan_typecable.value == "single_transponder": self.list.append(getConfigListEntry(_("Frequency"), self.scan_cab.frequency)) @@ -424,8 +419,6 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): self.list.append(getConfigListEntry(_("Modulation"), self.scan_cab.modulation)) self.list.append(getConfigListEntry(_("FEC"), self.scan_cab.fec)) self.list.append(getConfigListEntry(_("Network scan"), self.scan_networkScan)) - elif self.scan_typecable.value == "complete": - self.list.append(getConfigListEntry(_("Clear before scan"), self.scan_clearallservices)) elif nim.isCompatible("DVB-T"): if self.scan_typeterrestrial.value == "single_transponder": self.list.append(getConfigListEntry(_("Frequency"), self.scan_ter.frequency)) @@ -438,22 +431,8 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): self.list.append(getConfigListEntry(_("Guard interval mode"), self.scan_ter.guard)) self.list.append(getConfigListEntry(_("Hierarchy mode"), self.scan_ter.hierarchy)) self.list.append(getConfigListEntry(_("Network scan"), self.scan_networkScan)) - elif self.scan_typeterrestrial.value == "complete": - self.list.append(getConfigListEntry(_("Clear before scan"), self.scan_clearallservices)) - -# if (nim.isCompatible("DVB-S") and self.scan_type.type == "single_transponder") or \ -# (nim.isCompatbile("DVB-C") and self.scan_typecable.type == "single_transponder") or \ -# (nim.isCompatible("DVB-T") and self.scan_typeterrestrial.type == "single_transponder"): -# self.configElementSNR = getConfigListEntry(_("SNR"), self.scan_snr) -# self.list.append(self.configElementSNR) -# self.configElementACG = getConfigListEntry(_("AGC"), self.scan_agc) -# self.list.append(self.configElementACG) -# self.configElementBER = getConfigListEntry(_("BER"), self.scan_ber) -# self.list.append(self.configElementBER) -# self.statusTimer.start(500, False) -# else: -# self.statusTimer.stop() - + self.list.append(getConfigListEntry(_("Clear before scan"), self.scan_clearallservices)) + self.list.append(getConfigListEntry(_("Only Free scan"), self.scan_onlyfree)) self["config"].list = self.list self["config"].l.setList(self.list) @@ -540,6 +519,7 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): self.scan_typecable = ConfigSelection(default = "single_transponder", choices = [("single_transponder", _("Single transponder")), ("complete", _("Complete"))]) self.scan_typeterrestrial = ConfigSelection(default = "single_transponder", choices = [("single_transponder", _("Single transponder")), ("complete", _("Complete"))]) self.scan_clearallservices = ConfigSelection(default = "no", choices = [("no", _("no")), ("yes", _("yes")), ("yes_hold_feeds", _("yes (keep feeds)"))]) + self.scan_onlyfree = ConfigYesNo(default = False) self.scan_networkScan = ConfigYesNo(default = False) nim_list = [] @@ -663,9 +643,8 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): def keyGo(self): tlist = [] flags = None - extFlags = True - startScan = True + removeAll = True index_to_scan = int(self.scan_nims.value) if self.scan_nims == [ ]: @@ -703,10 +682,11 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): self.scan_sat.rolloff.index, self.scan_sat.pilot.index) flags = self.scan_networkScan.value and eComponentScan.scanNetworkSearch or 0 - extFlags = False + removeAll = False elif self.scan_type.value == "single_satellite": sat = self.satList[index_to_scan][self.scan_satselection[index_to_scan].index] getInitialTransponderList(tlist, sat[0]) + flags = self.scan_networkScan.value and eComponentScan.scanNetworkSearch or 0 elif self.scan_type.value == "multisat": SatList = nimmanager.getSatListForNim(index_to_scan) for x in self.multiscanlist: @@ -723,7 +703,7 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): fec, self.scan_cab.inversion.index) flags = self.scan_networkScan.value and eComponentScan.scanNetworkSearch or 0 - extFlags = False + removeAll = False elif self.scan_typecable.value == "complete": if config.Nims[index_to_scan].cable.scan_type.value == "provider": getInitialCableTransponderList(tlist, index_to_scan) @@ -743,20 +723,25 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): guard = self.scan_ter.guard.index, hierarchy = self.scan_ter.hierarchy.index) flags = self.scan_networkScan.value and eComponentScan.scanNetworkSearch or 0 - extFlags = False + removeAll = False elif self.scan_typeterrestrial.value == "complete": getInitialTerrestrialTransponderList(tlist, nimmanager.getTerrestrialDescription(index_to_scan)) if flags is None: flags = eComponentScan.scanNetworkSearch - if extFlags: - tmp = self.scan_clearallservices.value - if tmp == "yes": - flags |= eComponentScan.scanRemoveServices - elif tmp == "yes_hold_feeds": - flags |= eComponentScan.scanRemoveServices - flags |= eComponentScan.scanDontRemoveFeeds + tmp = self.scan_clearallservices.value + if tmp == "yes": + flags |= eComponentScan.scanRemoveServices + elif tmp == "yes_hold_feeds": + flags |= eComponentScan.scanRemoveServices + flags |= eComponentScan.scanDontRemoveFeeds + + if tmp != "no" and not removeAll: + flags |= eComponentScan.scanDontRemoveUnscanned + + if self.scan_onlyfree.value: + flags |= eComponentScan.scanOnlyFree for x in self["config"].list: x[1].save() -- 2.30.2