#include <lib/dvb/idvb.h>
-#include <dvbsi++/service_description_section.h>
-#include <dvbsi++/network_information_section.h>
-#include <dvbsi++/bouquet_association_section.h>
#include <dvbsi++/descriptor_tag.h>
#include <dvbsi++/service_descriptor.h>
#include <dvbsi++/satellite_delivery_system_descriptor.h>
#include <lib/base/eerror.h>
#include <lib/base/estring.h>
#include <errno.h>
-#include <set>
-#define SCAN_eDebug(x...) eDebug(x)
-#define SCAN_eDebugNoNewLine(x...) eDebugNoNewLine(x)
+static bool scan_debug;
+#define SCAN_eDebug(x...) do { if (scan_debug) eDebug(x); } while(0)
+#define SCAN_eDebugNoNewLine(x...) do { if (scan_debug) eDebugNoNewLine(x); } while(0)
DEFINE_REF(eDVBScan);
-eDVBScan::eDVBScan(iDVBChannel *channel): m_channel(channel)
+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)
{
+ scan_debug=debug;
if (m_channel->getDemux(m_demux))
SCAN_eDebug("scan: failed to allocate demux!");
m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
m_SDT = 0; m_BAT = 0; m_NIT = 0;
m_ready = 0;
-
+
/* check what we need */
m_ready_all = readySDT;
if (m_flags & scanSearchBAT)
m_ready_all |= readyBAT;
-
+
+ if (m_usePAT)
+ m_ready_all |= readyPAT;
+
if (m_ch_toScan.empty())
{
- eDebug("no channels left to scan.");
- eDebug("%d channels scanned, %d were unavailable.",
+ SCAN_eDebug("no channels left to scan.");
+ SCAN_eDebug("%d channels scanned, %d were unavailable.",
m_ch_scanned.size(), m_ch_unavailable.size());
- eDebug("%d channels in database.", m_new_channels.size());
+ SCAN_eDebug("%d channels in database.", m_new_channels.size());
m_event(evtFinish);
return -ENOENT;
}
RESULT eDVBScan::startFilter()
{
+ bool startSDT=true;
assert(m_demux);
-
+
/* only start required filters filter */
-
- m_SDT = 0;
- if (m_ready_all & readySDT)
+ if (m_ready_all & readyPAT)
+ startSDT = m_ready & readyPAT;
+
+ m_SDT = 0;
+ if (startSDT && (m_ready_all & readySDT))
{
m_SDT = new eTable<ServiceDescriptionSection>();
- if (m_SDT->start(m_demux, eDVBSDTSpec()))
+ if (m_ready & readyPAT && m_ready & validPAT)
+ {
+ std::vector<ProgramAssociationSection*>::const_iterator i =
+ m_PAT->getSections().begin();
+ assert(i != m_PAT->getSections().end());
+ int tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
+ if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
+ return -1;
+ }
+ else if (m_SDT->start(m_demux, eDVBSDTSpec()))
return -1;
CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
}
- m_NIT = 0;
- if (m_ready_all & readyNIT)
+ if (!(m_ready & readyPAT))
{
- m_NIT = new eTable<NetworkInformationSection>();
- if (m_NIT->start(m_demux, eDVBNITSpec()))
- return -1;
- CONNECT(m_NIT->tableReady, eDVBScan::NITready);
- }
+ m_PAT = 0;
+ if (m_ready_all & readyPAT)
+ {
+ m_PAT = new eTable<ProgramAssociationSection>();
+ if (m_PAT->start(m_demux, eDVBPATSpec()))
+ return -1;
+ CONNECT(m_PAT->tableReady, eDVBScan::PATready);
+ }
- m_BAT = 0;
- if (m_ready_all & readyBAT)
- {
- m_BAT = new eTable<BouquetAssociationSection>();
- if (m_BAT->start(m_demux, eDVBBATSpec()))
- return -1;
- CONNECT(m_BAT->tableReady, eDVBScan::BATready);
+ m_NIT = 0;
+ if (m_ready_all & readyNIT)
+ {
+ m_NIT = new eTable<NetworkInformationSection>();
+ if (m_NIT->start(m_demux, eDVBNITSpec()))
+ return -1;
+ CONNECT(m_NIT->tableReady, eDVBScan::NITready);
+ }
+
+ m_BAT = 0;
+ if (m_ready_all & readyBAT)
+ {
+ m_BAT = new eTable<BouquetAssociationSection>();
+ if (m_BAT->start(m_demux, eDVBBATSpec()))
+ return -1;
+ CONNECT(m_BAT->tableReady, eDVBScan::BATready);
+ }
}
-
+
return 0;
}
channelDone();
}
+void eDVBScan::PATready(int err)
+{
+ SCAN_eDebug("got pat");
+ m_ready |= readyPAT;
+ if (!err)
+ m_ready |= validPAT;
+ startFilter(); // for starting the SDT filter
+}
+
void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
{
/* add it to the list of known channels. */
if (m_ready & validSDT)
{
unsigned long hash = 0;
+
+ // m_ch_current is not set, when eDVBScan is just used for a SDT update
+ if (!m_ch_current)
+ m_channel->getCurrentFrontendParameters(m_ch_current);
+
m_ch_current->getHash(hash);
eDVBNamespace dvbnamespace = buildNamespace(
if ( m_chid_current.dvbnamespace.get() != -1 &&
((ns.get() ^ m_chid_current.dvbnamespace.get()) & 0xFFFF0000))
- eDebug("dropping this transponder, it's on another satellite.");
+ SCAN_eDebug("dropping this transponder, it's on another satellite.");
else
{
addChannelToScan(
These are the reasons for adding the transponder
here, and not before.
*/
-
+
if (!m_chid_current)
eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
else
nextChannel();
}
-void eDVBScan::insertInto(iDVBChannelList *db)
+void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
{
if (m_flags & scanRemoveServices)
{
eDVBChannelID chid;
if (m_flags & scanDontRemoveFeeds)
chid.dvbnamespace = eDVBNamespace((*x)<<16);
- eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
+// eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
db->removeServices(chid, *x);
}
}
ePtr<eDVBService> dvb_service;
if (!db->getService(service->first, dvb_service))
{
- *dvb_service = *service->second;
- dvb_service->m_flags &= ~eDVBService::dxNewFound;
+ if (dvb_service->m_flags & eDVBService::dxNoSDT)
+ continue;
+ if (!(dvb_service->m_flags & eDVBService::dxHoldName))
+ {
+ dvb_service->m_service_name = service->second->m_service_name;
+ dvb_service->m_service_name_sort = service->second->m_service_name_sort;
+ }
+ dvb_service->m_provider_name = service->second->m_provider_name;
+ if (service->second->m_ca.size())
+ dvb_service->m_ca = service->second->m_ca;
+ if (!dontRemoveOldFlags) // do not remove new found flags when not wished
+ dvb_service->m_flags &= ~eDVBService::dxNewFound;
}
else
{
SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
- /* save correct CHID for this channel if this is an ACTUAL_SDT */
- if (sdt.getTableId() == TID_SDT_ACTUAL)
- m_chid_current = chid;
-
+ /* save correct CHID for this channel */
+ m_chid_current = chid;
+
for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
{
SCAN_eDebugNoNewLine("SID %04x: ", (*s)->getServiceId());
for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
{
SCAN_eDebugNoNewLine("%04x ", *i);
- service->m_ca.insert(*i);
+ service->m_ca.push_front(*i);
}
SCAN_eDebug("");
break;