1 #include <lib/dvb/idvb.h>
2 #include <dvbsi++/descriptor_tag.h>
3 #include <dvbsi++/service_descriptor.h>
4 #include <dvbsi++/satellite_delivery_system_descriptor.h>
5 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
6 #include <dvbsi++/cable_delivery_system_descriptor.h>
7 #include <dvbsi++/ca_identifier_descriptor.h>
8 #include <lib/dvb/specs.h>
9 #include <lib/dvb/esection.h>
10 #include <lib/dvb/scan.h>
11 #include <lib/dvb/frontend.h>
12 #include <lib/base/eerror.h>
13 #include <lib/base/estring.h>
16 static bool scan_debug;
17 #define SCAN_eDebug(x...) do { if (scan_debug) eDebug(x); } while(0)
18 #define SCAN_eDebugNoNewLine(x...) do { if (scan_debug) eDebugNoNewLine(x); } while(0)
22 eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug)
23 :m_channel(channel), m_channel_state(iDVBChannel::state_idle)
24 ,m_ready(0), m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT)
25 ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0), m_usePAT(usePAT)
28 if (m_channel->getDemux(m_demux))
29 SCAN_eDebug("scan: failed to allocate demux!");
30 m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
37 int eDVBScan::isValidONIDTSID(int orbital_position, eOriginalNetworkID onid, eTransportStreamID tsid)
45 return orbital_position == 192;
47 return tsid != 0x00B0;
49 return abs(orbital_position-282) < 6;
51 return onid.get() < 0xFF00;
55 eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash)
57 // on valid ONIDs, ignore frequency ("sub network") part
58 if (isValidONIDTSID((hash >> 16) & 0xFFFF, onid, tsid))
60 return eDVBNamespace(hash);
63 void eDVBScan::stateChange(iDVBChannel *ch)
66 if (ch->getState(state))
68 if (m_channel_state == state)
71 if (state == iDVBChannel::state_ok)
74 m_channel_state = state;
75 } else if (state == iDVBChannel::state_failed)
77 m_ch_unavailable.push_back(m_ch_current);
80 /* unavailable will timeout, anyway. */
83 RESULT eDVBScan::nextChannel()
85 ePtr<iDVBFrontend> fe;
87 m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0;
91 m_pat_tsid = eTransportStreamID();
93 /* check what we need */
94 m_ready_all = readySDT;
96 if (m_flags & scanNetworkSearch)
97 m_ready_all |= readyNIT;
99 if (m_flags & scanSearchBAT)
100 m_ready_all |= readyBAT;
103 m_ready_all |= readyPAT;
105 if (m_ch_toScan.empty())
107 SCAN_eDebug("no channels left to scan.");
108 SCAN_eDebug("%d channels scanned, %d were unavailable.",
109 m_ch_scanned.size(), m_ch_unavailable.size());
110 SCAN_eDebug("%d channels in database.", m_new_channels.size());
115 m_ch_current = m_ch_toScan.front();
117 m_ch_toScan.pop_front();
119 if (m_channel->getFrontend(fe))
125 m_chid_current = eDVBChannelID();
127 m_channel_state = iDVBChannel::state_idle;
129 if (fe->tune(*m_ch_current))
130 return nextChannel();
136 RESULT eDVBScan::startFilter()
141 /* only start required filters filter */
143 if (m_ready_all & readyPAT)
144 startSDT = m_ready & readyPAT;
147 if (startSDT && (m_ready_all & readySDT))
149 m_SDT = new eTable<ServiceDescriptionSection>();
151 if (m_ready & readyPAT && m_ready & validPAT)
153 std::vector<ProgramAssociationSection*>::const_iterator i =
154 m_PAT->getSections().begin();
155 assert(i != m_PAT->getSections().end());
156 tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
157 m_pat_tsid = eTransportStreamID(tsid);
158 for (; i != m_PAT->getSections().end(); ++i)
160 const ProgramAssociationSection &pat = **i;
161 ProgramAssociationConstIterator program = pat.getPrograms()->begin();
162 for (; program != pat.getPrograms()->end(); ++program)
163 m_pmts_to_read.insert(std::pair<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
165 m_PMT = new eTable<ProgramMapSection>();
166 CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
169 // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
172 m_ch_current->getSystem(type);
173 if (type == iDVBFrontend::feCable)
175 eDVBFrontendParametersCable parm;
176 m_ch_current->getDVBC(parm);
177 if ((tsid == 0x00d7 && abs(parm.frequency-618000) < 2000) ||
178 (tsid == 0x00d8 && abs(parm.frequency-626000) < 2000))
185 if (m_SDT->start(m_demux, eDVBSDTSpec()))
188 else if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
190 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
193 if (!(m_ready & readyPAT))
196 if (m_ready_all & readyPAT)
198 m_PAT = new eTable<ProgramAssociationSection>();
199 if (m_PAT->start(m_demux, eDVBPATSpec()))
201 CONNECT(m_PAT->tableReady, eDVBScan::PATready);
205 if (m_ready_all & readyNIT)
207 m_NIT = new eTable<NetworkInformationSection>();
208 if (m_NIT->start(m_demux, eDVBNITSpec()))
210 CONNECT(m_NIT->tableReady, eDVBScan::NITready);
214 if (m_ready_all & readyBAT)
216 m_BAT = new eTable<BouquetAssociationSection>();
217 if (m_BAT->start(m_demux, eDVBBATSpec()))
219 CONNECT(m_BAT->tableReady, eDVBScan::BATready);
226 void eDVBScan::SDTready(int err)
228 SCAN_eDebug("got sdt %d", err);
235 void eDVBScan::NITready(int err)
237 SCAN_eDebug("got nit, err %d", err);
244 void eDVBScan::BATready(int err)
246 SCAN_eDebug("got bat");
253 void eDVBScan::PATready(int err)
255 SCAN_eDebug("got pat");
259 startFilter(); // for starting the SDT filter
262 void eDVBScan::PMTready(int err)
264 SCAN_eDebug("got pmt %d", err);
267 bool scrambled = false;
268 bool have_audio = false;
269 bool have_video = false;
270 unsigned short pcrpid = 0xFFFF;
271 std::vector<ProgramMapSection*>::const_iterator i;
272 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
274 const ProgramMapSection &pmt = **i;
275 if (pcrpid == 0xFFFF)
276 pcrpid = pmt.getPcrPid();
278 SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
279 ElementaryStreamInfoConstIterator es;
280 for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
282 int isaudio = 0, isvideo = 0, is_scrambled = 0;
283 switch ((*es)->getType())
285 case 0x1b: // AVC Video Stream (MPEG4 H264)
286 case 0x01: // MPEG 1 video
287 case 0x02: // MPEG 2 video
289 //break; fall through !!!
290 case 0x03: // MPEG 1 audio
291 case 0x04: // MPEG 2 audio:
294 //break; fall through !!!
295 case 0x06: // PES Private
296 case 0x81: // user private
297 /* PES private can contain AC-3, DTS or lots of other stuff.
298 check descriptors to get the exact type. */
299 for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
300 desc != (*es)->getDescriptors()->end(); ++desc)
302 uint8_t tag = (*desc)->getTag();
303 if (!isaudio && !isvideo)
313 case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
315 /* libdvbsi++ doesn't yet support this descriptor type, so work around. */
316 if ((*desc)->getLength() != 4)
318 unsigned char descr[6];
319 (*desc)->writeToBuffer(descr);
320 int format_identifier = (descr[2] << 24) | (descr[3] << 16) | (descr[4] << 8) | (descr[5]);
321 switch (format_identifier)
332 if (tag == CA_DESCRIPTOR)
346 for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
347 desc != pmt.getDescriptors()->end(); ++desc)
349 if ((*desc)->getTag() == CA_DESCRIPTOR)
353 m_pmt_in_progress->second.scrambled = scrambled;
355 m_pmt_in_progress->second.serviceType = 1;
356 else if ( have_audio )
357 m_pmt_in_progress->second.serviceType = 2;
359 m_pmt_in_progress->second.serviceType = 100;
361 if (err == -2) // aborted in sdt progress
362 m_pmts_to_read.erase(m_pmt_in_progress++);
363 else if (m_pmt_running)
367 m_pmt_in_progress = m_pmts_to_read.begin();
368 m_pmt_running = true;
371 if (m_pmt_in_progress != m_pmts_to_read.end())
372 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first));
375 m_pmt_running = false;
381 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
383 /* add it to the list of known channels. */
385 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
388 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
390 /* check if we don't already have that channel ... */
393 feparm->getSystem(type);
397 case iDVBFrontend::feSatellite:
399 eDVBFrontendParametersSatellite parm;
400 feparm->getDVBS(parm);
401 SCAN_eDebug("try to add %d %d %d %d %d %d",
402 parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
405 case iDVBFrontend::feCable:
407 eDVBFrontendParametersCable parm;
408 feparm->getDVBC(parm);
409 SCAN_eDebug("try to add %d %d %d %d",
410 parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
413 case iDVBFrontend::feTerrestrial:
415 eDVBFrontendParametersTerrestrial parm;
416 feparm->getDVBT(parm);
417 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
418 parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
419 parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
425 /* ... in the list of channels to scan */
426 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
428 if (sameChannel(*i, feparm))
432 *i = feparm; // update
433 SCAN_eDebug("update");
437 SCAN_eDebug("remove dupe");
438 m_ch_toScan.erase(i++);
448 SCAN_eDebug("already in todo list");
452 /* ... in the list of successfully scanned channels */
453 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
454 if (sameChannel(*i, feparm))
456 SCAN_eDebug("successfully scanned");
460 /* ... in the list of unavailable channels */
461 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
462 if (sameChannel(*i, feparm, true))
464 SCAN_eDebug("scanned but not available");
468 /* ... on the current channel */
469 if (sameChannel(m_ch_current, feparm))
471 SCAN_eDebug("is current");
475 SCAN_eDebug("really add");
476 /* otherwise, add it to the todo list. */
477 m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
480 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
483 if (ch1->calculateDifference(ch2, diff, exact))
485 if (diff < 4000) // more than 4mhz difference?
490 void eDVBScan::channelDone()
492 if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
494 unsigned long hash = 0;
496 // m_ch_current is not set, when eDVBScan is just used for a SDT update
499 unsigned int channelFlags;
500 m_channel->getCurrentFrontendParameters(m_ch_current);
501 m_ch_current->getFlags(channelFlags);
502 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
503 m_flags |= scanOnlyFree;
506 m_ch_current->getHash(hash);
508 eDVBNamespace dvbnamespace = buildNamespace(
509 (**m_SDT->getSections().begin()).getOriginalNetworkId(),
510 (**m_SDT->getSections().begin()).getTransportStreamId(),
513 SCAN_eDebug("SDT: ");
514 std::vector<ServiceDescriptionSection*>::const_iterator i;
515 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
516 processSDT(dvbnamespace, **i);
517 m_ready &= ~validSDT;
520 if (m_ready & validNIT)
523 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
524 m_ch_current->getSystem(system);
525 SCAN_eDebug("dumping NIT");
526 if (m_flags & clearToScanOnFirstNIT)
528 m_ch_toScan_backup = m_ch_toScan;
531 std::vector<NetworkInformationSection*>::const_iterator i;
532 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
534 const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
536 for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin());
537 tsinfo != tsinfovec.end(); ++tsinfo)
539 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
540 (*tsinfo)->getOriginalNetworkId());
542 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
543 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
545 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
546 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
548 switch ((*desc)->getTag())
550 case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
552 if (system != iDVBFrontend::feCable)
553 break; // when current locked transponder is no cable transponder ignore this descriptor
554 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
555 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
556 eDVBFrontendParametersCable cable;
558 feparm->setDVBC(cable);
560 unsigned long hash=0;
561 feparm->getHash(hash);
562 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
565 eDVBChannelID(ns, tsid, onid),
569 case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
571 if (system != iDVBFrontend::feTerrestrial)
572 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
573 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
574 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
575 eDVBFrontendParametersTerrestrial terr;
577 feparm->setDVBT(terr);
579 unsigned long hash=0;
580 feparm->getHash(hash);
581 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
584 eDVBChannelID(ns, tsid, onid),
588 case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
590 if (system != iDVBFrontend::feSatellite)
591 break; // when current locked transponder is no satellite transponder ignore this descriptor
593 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
594 if (d.getFrequency() < 10000)
597 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
598 eDVBFrontendParametersSatellite sat;
601 eDVBFrontendParametersSatellite p;
602 m_ch_current->getDVBS(p);
604 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
605 sat.orbital_position = p.orbital_position;
607 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
609 SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
610 sat.orbital_position = p.orbital_position;
613 feparm->setDVBS(sat);
615 if ( p.orbital_position != sat.orbital_position)
616 SCAN_eDebug("dropping this transponder, it's on another satellite.");
619 unsigned long hash=0;
620 feparm->getHash(hash);
622 eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
628 SCAN_eDebug("descr<%x>", (*desc)->getTag());
636 /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
637 no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
640 This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
642 if (m_flags & clearToScanOnFirstNIT)
644 if (m_ch_toScan.empty())
646 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
647 m_ch_toScan = m_ch_toScan_backup;
649 m_flags &= ~clearToScanOnFirstNIT;
651 m_ready &= ~validNIT;
654 if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
656 if (m_abort_current_pmt)
658 m_abort_current_pmt = false;
664 SCAN_eDebug("channel done!");
666 /* if we had services on this channel, we declare
667 this channels as "known good". add it.
669 (TODO: not yet implemented)
670 a NIT entry could have possible overridden
671 our frontend data with more exact data.
673 (TODO: not yet implemented)
674 the tuning process could have lead to more
675 exact data than the user entered.
677 The channel id was probably corrected
678 by the data written in the SDT. this is
679 important, as "initial transponder lists"
680 usually don't have valid CHIDs (and that's
683 These are the reasons for adding the transponder
684 here, and not before.
687 for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
690 eServiceReferenceDVB ref;
691 ePtr<eDVBService> service = new eDVBService;
695 unsigned long hash = 0;
697 // m_ch_current is not set, when eDVBScan is just used for a SDT update
700 unsigned int channelFlags;
701 m_channel->getCurrentFrontendParameters(m_ch_current);
702 m_ch_current->getFlags(channelFlags);
703 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
704 m_flags |= scanOnlyFree;
707 m_ch_current->getHash(hash);
709 m_chid_current = eDVBChannelID(
710 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
711 m_pat_tsid, eOriginalNetworkID(0));
714 if (m_pmt_in_progress->second.serviceType == 1)
715 SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
716 else if (m_pmt_in_progress->second.serviceType == 2)
717 SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
719 SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
721 ref.set(m_chid_current);
722 ref.setServiceID(m_pmt_in_progress->first);
723 ref.setServiceType(m_pmt_in_progress->second.serviceType);
725 if (!m_ch_current->getSystem(type))
729 memset(pname, 0, sizeof(pname));
730 memset(sname, 0, sizeof(sname));
733 case iDVBFrontend::feSatellite:
735 eDVBFrontendParametersSatellite parm;
736 m_ch_current->getDVBS(parm);
737 snprintf(sname, 255, "%d%c SID 0x%02x",
739 parm.polarisation ? 'V' : 'H',
740 m_pmt_in_progress->first);
741 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
742 parm.system ? "DVB-S2" : "DVB-S",
743 parm.modulation == 1 ? "QPSK" : "8PSK",
745 parm.polarisation ? 'V' : 'H',
746 parm.orbital_position/10,
747 parm.orbital_position%10,
748 parm.orbital_position > 0 ? 'E' : 'W');
751 case iDVBFrontend::feTerrestrial:
753 eDVBFrontendParametersTerrestrial parm;
754 m_ch_current->getDVBT(parm);
755 snprintf(sname, 255, "%d SID 0x%02x",
757 m_pmt_in_progress->first);
760 case iDVBFrontend::feCable:
762 eDVBFrontendParametersCable parm;
763 m_ch_current->getDVBC(parm);
764 snprintf(sname, 255, "%d SID 0x%02x",
766 m_pmt_in_progress->first);
770 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
771 service->m_service_name = convertDVBUTF8(sname);
772 service->genSortName();
773 service->m_provider_name = pname;
776 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
780 m_last_service = i.first;
781 m_event(evtNewService);
783 m_pmts_to_read.erase(m_pmt_in_progress++);
787 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
789 addKnownGoodChannel(m_chid_current, m_ch_current);
791 m_ch_scanned.push_back(m_ch_current);
793 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
795 if (sameChannel(*i, m_ch_current))
797 SCAN_eDebug("remove dupe 2");
798 m_ch_toScan.erase(i++);
807 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
811 m_ch_scanned.clear();
812 m_ch_unavailable.clear();
813 m_new_channels.clear();
814 m_new_services.clear();
815 m_last_service = m_new_services.end();
817 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
820 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
822 if (sameChannel(*i, *ii, true))
829 m_ch_toScan.push_back(*i);
835 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
837 if (m_flags & scanRemoveServices)
839 bool clearTerrestrial=false;
840 bool clearCable=false;
841 std::set<unsigned int> scanned_sat_positions;
843 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
844 for (;it != m_ch_scanned.end(); ++it)
846 if (m_flags & scanDontRemoveUnscanned)
847 db->removeServices(&(*(*it)));
851 (*it)->getSystem(system);
854 case iDVBFrontend::feSatellite:
856 eDVBFrontendParametersSatellite sat_parm;
857 (*it)->getDVBS(sat_parm);
858 scanned_sat_positions.insert(sat_parm.orbital_position);
861 case iDVBFrontend::feTerrestrial:
863 clearTerrestrial=true;
866 case iDVBFrontend::feCable:
875 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
877 if (m_flags & scanDontRemoveUnscanned)
878 db->removeServices(&(*(*it)));
882 (*it)->getSystem(system);
885 case iDVBFrontend::feSatellite:
887 eDVBFrontendParametersSatellite sat_parm;
888 (*it)->getDVBS(sat_parm);
889 scanned_sat_positions.insert(sat_parm.orbital_position);
892 case iDVBFrontend::feTerrestrial:
894 clearTerrestrial=true;
897 case iDVBFrontend::feCable:
906 if (clearTerrestrial)
909 chid.dvbnamespace=0xEEEE0000;
910 db->removeServices(chid);
915 chid.dvbnamespace=0xFFFF0000;
916 db->removeServices(chid);
918 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
921 if (m_flags & scanDontRemoveFeeds)
922 chid.dvbnamespace = eDVBNamespace((*x)<<16);
923 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
924 db->removeServices(chid, *x);
928 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
929 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
931 if (m_flags & scanOnlyFree)
933 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
934 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
936 db->addChannelToList(ch->first, ch->second);
939 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
940 service(m_new_services.begin()); service != m_new_services.end(); ++service)
942 ePtr<eDVBService> dvb_service;
943 if (!db->getService(service->first, dvb_service))
945 if (dvb_service->m_flags & eDVBService::dxNoSDT)
947 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
949 dvb_service->m_service_name = service->second->m_service_name;
950 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
952 dvb_service->m_provider_name = service->second->m_provider_name;
953 if (service->second->m_ca.size())
954 dvb_service->m_ca = service->second->m_ca;
955 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
956 dvb_service->m_flags &= ~eDVBService::dxNewFound;
960 db->addService(service->first, service->second);
961 if (!(m_flags & scanRemoveServices))
962 service->second->m_flags |= eDVBService::dxNewFound;
967 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
969 const ServiceDescriptionList &services = *sdt.getDescriptions();
970 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
971 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
973 /* save correct CHID for this channel */
974 m_chid_current = chid;
976 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
978 unsigned short service_id = (*s)->getServiceId();
979 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
982 if (m_flags & scanOnlyFree)
984 std::map<unsigned short, service>::iterator it =
985 m_pmts_to_read.find(service_id);
986 if (it != m_pmts_to_read.end())
988 if (it->second.scrambled)
990 SCAN_eDebug("is scrambled!");
995 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1000 eServiceReferenceDVB ref;
1001 ePtr<eDVBService> service = new eDVBService;
1004 ref.setServiceID(service_id);
1006 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1007 desc != (*s)->getDescriptors()->end(); ++desc)
1009 switch ((*desc)->getTag())
1011 case SERVICE_DESCRIPTOR:
1013 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1014 ref.setServiceType(d.getServiceType());
1015 service->m_service_name = convertDVBUTF8(d.getServiceName());
1016 service->genSortName();
1018 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1019 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1022 case CA_IDENTIFIER_DESCRIPTOR:
1024 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1025 const CaSystemIdList &caids = *d.getCaSystemIds();
1026 SCAN_eDebugNoNewLine("CA ");
1027 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1029 SCAN_eDebugNoNewLine("%04x ", *i);
1030 service->m_ca.push_front(*i);
1036 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1041 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1045 m_last_service = i.first;
1046 m_event(evtNewService);
1049 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1050 m_abort_current_pmt = true;
1052 m_pmts_to_read.erase(service_id);
1058 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1060 connection = new eConnection(this, m_event.connect(event));
1064 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1066 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1067 transponders_total = m_ch_toScan.size() + transponders_done;
1068 services = m_new_services.size();
1071 void eDVBScan::getLastServiceName(std::string &last_service_name)
1073 if (m_last_service == m_new_services.end())
1074 last_service_name = "";
1076 last_service_name = m_last_service->second->m_service_name;
1079 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1082 return m_channel->getFrontend(fe);
1087 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)