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<iDVBFrontend> &SWIG_OUTPUT);
SWIG_VOID(RESULT) getCurrentTransponder(ePtr<iDVBFrontendParameters> &SWIG_OUTPUT);
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");
{
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;
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;
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);
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<eDVBChannelID, channel>::const_iterator i(m_channels.begin());
i != m_channels.end(); ++i)
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);
}
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++;
return ret;
}
+RESULT eDVBDB::removeServices(iDVBFrontendParameters *feparm)
+{
+ int ret = -1;
+ std::set<eDVBChannelID> removed_chids;
+ std::map<eDVBChannelID, channel>::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<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
+ while(service != m_services.end())
+ {
+ eDVBChannelID chid;
+ service->first.getChannelID(chid);
+ std::set<eDVBChannelID>::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)
RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm)
{
channel ch;
+ std::map<eDVBChannelID, channel>::iterator it = m_channels.find(id);
assert(feparm);
ch.m_frontendParameters = feparm;
- m_channels.insert(std::pair<eDVBChannelID, channel>(id, ch));
+ if (it != m_channels.end())
+ it->second = ch;
+ else
+ m_channels.insert(std::pair<eDVBChannelID, channel>(id, ch));
return 0;
}
#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);
guard_interval, hierarchy, modulation);
}
-eDVBFrontendParameters::eDVBFrontendParameters(): m_type(-1)
+eDVBFrontendParameters::eDVBFrontendParameters()
+ :m_type(-1), m_flags(0)
{
}
eDVBFrontendParametersTerrestrial terrestrial;
};
int m_type;
+ int m_flags;
public:
eDVBFrontendParameters();
~eDVBFrontendParameters()
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
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;
~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;
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<iDVBFrontendParameters>, iDVBFrontendParametersPtr);
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))
{
ePtr<iDVBFrontend> 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;
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<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
+ }
+ m_PMT = new eTable<ProgramMapSection>();
+ CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
+ PMTready(-1);
// KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
{
void eDVBScan::SDTready(int err)
{
- SCAN_eDebug("got sdt");
+ SCAN_eDebug("got sdt %d", err);
m_ready |= readySDT;
if (!err)
m_ready |= validSDT;
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<ProgramMapSection*>::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. */
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);
if (m_ready & validNIT)
{
+ eDebug("validNIT");
int system;
std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
m_ch_current->getSystem(system);
}
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
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<eDVBService> 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<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(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
std::list<ePtr<iDVBFrontendParameters> >::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;
+ }
}
}
}
for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::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<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
service(m_new_services.begin()); service != m_new_services.end(); ++service)
{
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<eDVBService> 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<unsigned short, service>::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<eDVBService> 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<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
+
+ if (i.second)
+ {
+ m_last_service = i.first;
+ m_event(evtNewService);
}
}
-
- std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(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;
}
#include <dvbsi++/network_information_section.h>
#include <dvbsi++/bouquet_association_section.h>
#include <dvbsi++/program_association_section.h>
+#include <dvbsi++/program_map_section.h>
+
#include <lib/dvb/idemux.h>
#include <lib/dvb/esection.h>
#include <lib/dvb/db.h>
+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);
std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> > m_new_channels;
std::map<eServiceReferenceDVB, ePtr<eDVBService> > m_new_services;
std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator m_last_service;
-
+
+ std::map<unsigned short, service> m_pmts_to_read;
+ std::map<unsigned short, service>::iterator m_pmt_in_progress;
+ bool m_pmt_running;
+ bool m_abort_current_pmt;
+
std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan, m_ch_scanned, m_ch_unavailable;
ePtr<iDVBFrontendParameters> m_ch_current;
eDVBChannelID m_chid_current;
-
+ eTransportStreamID m_pat_tsid;
+
ePtr<eTable<ServiceDescriptionSection> > m_SDT;
ePtr<eTable<NetworkInformationSection> > m_NIT;
ePtr<eTable<BouquetAssociationSection> > m_BAT;
ePtr<eTable<ProgramAssociationSection> > m_PAT;
-
+ ePtr<eTable<ProgramMapSection> > 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);
enum {
scanNetworkSearch = 1, scanSearchBAT = 2,
scanRemoveServices = 4, scanDontRemoveFeeds = 8,
- clearToScanOnFirstNIT = 16 };
+ scanDontRemoveUnscanned = 16,
+ clearToScanOnFirstNIT = 32, scanOnlyFree = 64 };
void start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags);
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])
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))
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))
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)
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 = []
def keyGo(self):
tlist = []
flags = None
- extFlags = True
-
startScan = True
+ removeAll = True
index_to_scan = int(self.scan_nims.value)
if self.scan_nims == [ ]:
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:
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)
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()