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 switch ((*desc)->getTag())
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)
343 for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
344 desc != pmt.getDescriptors()->end(); ++desc)
346 if ((*desc)->getTag() == CA_DESCRIPTOR)
350 m_pmt_in_progress->second.scrambled = scrambled;
352 m_pmt_in_progress->second.serviceType = 1;
353 else if ( have_audio )
354 m_pmt_in_progress->second.serviceType = 2;
356 m_pmt_in_progress->second.serviceType = 100;
358 if (err == -2) // aborted in sdt progress
359 m_pmts_to_read.erase(m_pmt_in_progress++);
360 else if (m_pmt_running)
364 m_pmt_in_progress = m_pmts_to_read.begin();
365 m_pmt_running = true;
368 if (m_pmt_in_progress != m_pmts_to_read.end())
369 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first));
372 m_pmt_running = false;
378 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
380 /* add it to the list of known channels. */
382 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
385 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
387 /* check if we don't already have that channel ... */
390 feparm->getSystem(type);
394 case iDVBFrontend::feSatellite:
396 eDVBFrontendParametersSatellite parm;
397 feparm->getDVBS(parm);
398 SCAN_eDebug("try to add %d %d %d %d %d %d",
399 parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
402 case iDVBFrontend::feCable:
404 eDVBFrontendParametersCable parm;
405 feparm->getDVBC(parm);
406 SCAN_eDebug("try to add %d %d %d %d",
407 parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
410 case iDVBFrontend::feTerrestrial:
412 eDVBFrontendParametersTerrestrial parm;
413 feparm->getDVBT(parm);
414 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
415 parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
416 parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
422 /* ... in the list of channels to scan */
423 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
425 if (sameChannel(*i, feparm))
429 *i = feparm; // update
430 SCAN_eDebug("update");
434 SCAN_eDebug("remove dupe");
435 m_ch_toScan.erase(i++);
445 SCAN_eDebug("already in todo list");
449 /* ... in the list of successfully scanned channels */
450 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
451 if (sameChannel(*i, feparm))
453 SCAN_eDebug("successfully scanned");
457 /* ... in the list of unavailable channels */
458 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
459 if (sameChannel(*i, feparm, true))
461 SCAN_eDebug("scanned but not available");
465 /* ... on the current channel */
466 if (sameChannel(m_ch_current, feparm))
468 SCAN_eDebug("is current");
472 SCAN_eDebug("really add");
473 /* otherwise, add it to the todo list. */
474 m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
477 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
480 if (ch1->calculateDifference(ch2, diff, exact))
482 if (diff < 4000) // more than 4mhz difference?
487 void eDVBScan::channelDone()
489 if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
491 unsigned long hash = 0;
493 // m_ch_current is not set, when eDVBScan is just used for a SDT update
496 unsigned int channelFlags;
497 m_channel->getCurrentFrontendParameters(m_ch_current);
498 m_ch_current->getFlags(channelFlags);
499 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
500 m_flags |= scanOnlyFree;
503 m_ch_current->getHash(hash);
505 eDVBNamespace dvbnamespace = buildNamespace(
506 (**m_SDT->getSections().begin()).getOriginalNetworkId(),
507 (**m_SDT->getSections().begin()).getTransportStreamId(),
510 SCAN_eDebug("SDT: ");
511 std::vector<ServiceDescriptionSection*>::const_iterator i;
512 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
513 processSDT(dvbnamespace, **i);
514 m_ready &= ~validSDT;
517 if (m_ready & validNIT)
520 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
521 m_ch_current->getSystem(system);
522 SCAN_eDebug("dumping NIT");
523 if (m_flags & clearToScanOnFirstNIT)
525 m_ch_toScan_backup = m_ch_toScan;
528 std::vector<NetworkInformationSection*>::const_iterator i;
529 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
531 const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
533 for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin());
534 tsinfo != tsinfovec.end(); ++tsinfo)
536 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
537 (*tsinfo)->getOriginalNetworkId());
539 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
540 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
542 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
543 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
545 switch ((*desc)->getTag())
547 case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
549 if (system != iDVBFrontend::feCable)
550 break; // when current locked transponder is no cable transponder ignore this descriptor
551 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
552 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
553 eDVBFrontendParametersCable cable;
555 feparm->setDVBC(cable);
557 unsigned long hash=0;
558 feparm->getHash(hash);
559 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
562 eDVBChannelID(ns, tsid, onid),
566 case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
568 if (system != iDVBFrontend::feTerrestrial)
569 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
570 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
571 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
572 eDVBFrontendParametersTerrestrial terr;
574 feparm->setDVBT(terr);
576 unsigned long hash=0;
577 feparm->getHash(hash);
578 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
581 eDVBChannelID(ns, tsid, onid),
585 case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
587 if (system != iDVBFrontend::feSatellite)
588 break; // when current locked transponder is no satellite transponder ignore this descriptor
590 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
591 if (d.getFrequency() < 10000)
594 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
595 eDVBFrontendParametersSatellite sat;
598 eDVBFrontendParametersSatellite p;
599 m_ch_current->getDVBS(p);
601 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
602 sat.orbital_position = p.orbital_position;
604 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
606 SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
607 sat.orbital_position = p.orbital_position;
610 feparm->setDVBS(sat);
612 if ( p.orbital_position != sat.orbital_position)
613 SCAN_eDebug("dropping this transponder, it's on another satellite.");
616 unsigned long hash=0;
617 feparm->getHash(hash);
619 eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
625 SCAN_eDebug("descr<%x>", (*desc)->getTag());
633 /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
634 no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
637 This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
639 if (m_flags & clearToScanOnFirstNIT)
641 if (m_ch_toScan.empty())
643 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
644 m_ch_toScan = m_ch_toScan_backup;
646 m_flags &= ~clearToScanOnFirstNIT;
648 m_ready &= ~validNIT;
651 if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
653 if (m_abort_current_pmt)
655 m_abort_current_pmt = false;
661 SCAN_eDebug("channel done!");
663 /* if we had services on this channel, we declare
664 this channels as "known good". add it.
666 (TODO: not yet implemented)
667 a NIT entry could have possible overridden
668 our frontend data with more exact data.
670 (TODO: not yet implemented)
671 the tuning process could have lead to more
672 exact data than the user entered.
674 The channel id was probably corrected
675 by the data written in the SDT. this is
676 important, as "initial transponder lists"
677 usually don't have valid CHIDs (and that's
680 These are the reasons for adding the transponder
681 here, and not before.
684 for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
687 eServiceReferenceDVB ref;
688 ePtr<eDVBService> service = new eDVBService;
692 unsigned long hash = 0;
694 // m_ch_current is not set, when eDVBScan is just used for a SDT update
697 unsigned int channelFlags;
698 m_channel->getCurrentFrontendParameters(m_ch_current);
699 m_ch_current->getFlags(channelFlags);
700 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
701 m_flags |= scanOnlyFree;
704 m_ch_current->getHash(hash);
706 m_chid_current = eDVBChannelID(
707 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
708 m_pat_tsid, eOriginalNetworkID(0));
711 if (m_pmt_in_progress->second.serviceType == 1)
712 SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
713 else if (m_pmt_in_progress->second.serviceType == 2)
714 SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
716 SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
718 ref.set(m_chid_current);
719 ref.setServiceID(m_pmt_in_progress->first);
720 ref.setServiceType(m_pmt_in_progress->second.serviceType);
722 if (!m_ch_current->getSystem(type))
726 memset(pname, 0, sizeof(pname));
727 memset(sname, 0, sizeof(sname));
730 case iDVBFrontend::feSatellite:
732 eDVBFrontendParametersSatellite parm;
733 m_ch_current->getDVBS(parm);
734 snprintf(sname, 255, "%d%c SID 0x%02x",
736 parm.polarisation ? 'V' : 'H',
737 m_pmt_in_progress->first);
738 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
739 parm.system ? "DVB-S2" : "DVB-S",
740 parm.modulation == 1 ? "QPSK" : "8PSK",
742 parm.polarisation ? 'V' : 'H',
743 parm.orbital_position/10,
744 parm.orbital_position%10,
745 parm.orbital_position > 0 ? 'E' : 'W');
748 case iDVBFrontend::feTerrestrial:
750 eDVBFrontendParametersTerrestrial parm;
751 m_ch_current->getDVBT(parm);
752 snprintf(sname, 255, "%d SID 0x%02x",
754 m_pmt_in_progress->first);
757 case iDVBFrontend::feCable:
759 eDVBFrontendParametersCable parm;
760 m_ch_current->getDVBC(parm);
761 snprintf(sname, 255, "%d SID 0x%02x",
763 m_pmt_in_progress->first);
767 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
768 service->m_service_name = convertDVBUTF8(sname);
769 service->genSortName();
770 service->m_provider_name = pname;
773 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
777 m_last_service = i.first;
778 m_event(evtNewService);
780 m_pmts_to_read.erase(m_pmt_in_progress++);
784 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
786 addKnownGoodChannel(m_chid_current, m_ch_current);
788 m_ch_scanned.push_back(m_ch_current);
790 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
792 if (sameChannel(*i, m_ch_current))
794 SCAN_eDebug("remove dupe 2");
795 m_ch_toScan.erase(i++);
804 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
808 m_ch_scanned.clear();
809 m_ch_unavailable.clear();
810 m_new_channels.clear();
811 m_new_services.clear();
812 m_last_service = m_new_services.end();
814 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
817 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
819 if (sameChannel(*i, *ii, true))
826 m_ch_toScan.push_back(*i);
832 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
834 if (m_flags & scanRemoveServices)
836 bool clearTerrestrial=false;
837 bool clearCable=false;
838 std::set<unsigned int> scanned_sat_positions;
840 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
841 for (;it != m_ch_scanned.end(); ++it)
843 if (m_flags & scanDontRemoveUnscanned)
844 db->removeServices(&(*(*it)));
848 (*it)->getSystem(system);
851 case iDVBFrontend::feSatellite:
853 eDVBFrontendParametersSatellite sat_parm;
854 (*it)->getDVBS(sat_parm);
855 scanned_sat_positions.insert(sat_parm.orbital_position);
858 case iDVBFrontend::feTerrestrial:
860 clearTerrestrial=true;
863 case iDVBFrontend::feCable:
872 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
874 if (m_flags & scanDontRemoveUnscanned)
875 db->removeServices(&(*(*it)));
879 (*it)->getSystem(system);
882 case iDVBFrontend::feSatellite:
884 eDVBFrontendParametersSatellite sat_parm;
885 (*it)->getDVBS(sat_parm);
886 scanned_sat_positions.insert(sat_parm.orbital_position);
889 case iDVBFrontend::feTerrestrial:
891 clearTerrestrial=true;
894 case iDVBFrontend::feCable:
903 if (clearTerrestrial)
906 chid.dvbnamespace=0xEEEE0000;
907 db->removeServices(chid);
912 chid.dvbnamespace=0xFFFF0000;
913 db->removeServices(chid);
915 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
918 if (m_flags & scanDontRemoveFeeds)
919 chid.dvbnamespace = eDVBNamespace((*x)<<16);
920 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
921 db->removeServices(chid, *x);
925 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
926 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
928 if (m_flags & scanOnlyFree)
930 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
931 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
933 db->addChannelToList(ch->first, ch->second);
936 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
937 service(m_new_services.begin()); service != m_new_services.end(); ++service)
939 ePtr<eDVBService> dvb_service;
940 if (!db->getService(service->first, dvb_service))
942 if (dvb_service->m_flags & eDVBService::dxNoSDT)
944 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
946 dvb_service->m_service_name = service->second->m_service_name;
947 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
949 dvb_service->m_provider_name = service->second->m_provider_name;
950 if (service->second->m_ca.size())
951 dvb_service->m_ca = service->second->m_ca;
952 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
953 dvb_service->m_flags &= ~eDVBService::dxNewFound;
957 db->addService(service->first, service->second);
958 if (!(m_flags & scanRemoveServices))
959 service->second->m_flags |= eDVBService::dxNewFound;
964 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
966 const ServiceDescriptionList &services = *sdt.getDescriptions();
967 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
968 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
970 /* save correct CHID for this channel */
971 m_chid_current = chid;
973 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
975 unsigned short service_id = (*s)->getServiceId();
976 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
979 if (m_flags & scanOnlyFree)
981 std::map<unsigned short, service>::iterator it =
982 m_pmts_to_read.find(service_id);
983 if (it != m_pmts_to_read.end())
985 if (it->second.scrambled)
987 SCAN_eDebug("is scrambled!");
992 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
997 eServiceReferenceDVB ref;
998 ePtr<eDVBService> service = new eDVBService;
1001 ref.setServiceID(service_id);
1003 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1004 desc != (*s)->getDescriptors()->end(); ++desc)
1006 switch ((*desc)->getTag())
1008 case SERVICE_DESCRIPTOR:
1010 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1011 ref.setServiceType(d.getServiceType());
1012 service->m_service_name = convertDVBUTF8(d.getServiceName());
1013 service->genSortName();
1015 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1016 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1019 case CA_IDENTIFIER_DESCRIPTOR:
1021 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1022 const CaSystemIdList &caids = *d.getCaSystemIds();
1023 SCAN_eDebugNoNewLine("CA ");
1024 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1026 SCAN_eDebugNoNewLine("%04x ", *i);
1027 service->m_ca.push_front(*i);
1033 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1038 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1042 m_last_service = i.first;
1043 m_event(evtNewService);
1046 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1047 m_abort_current_pmt = true;
1049 m_pmts_to_read.erase(service_id);
1055 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1057 connection = new eConnection(this, m_event.connect(event));
1061 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1063 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1064 transponders_total = m_ch_toScan.size() + transponders_done;
1065 services = m_new_services.size();
1068 void eDVBScan::getLastServiceName(std::string &last_service_name)
1070 if (m_last_service == m_new_services.end())
1071 last_service_name = "";
1073 last_service_name = m_last_service->second->m_service_name;
1076 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1079 return m_channel->getFrontend(fe);
1084 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)