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)
312 case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
314 /* libdvbsi++ doesn't yet support this descriptor type, so work around. */
315 if ((*desc)->getLength() != 4)
317 unsigned char descr[6];
318 (*desc)->writeToBuffer(descr);
319 int format_identifier = (descr[2] << 24) | (descr[3] << 16) | (descr[4] << 8) | (descr[5]);
320 switch (format_identifier)
331 if (tag == CA_DESCRIPTOR)
345 for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
346 desc != pmt.getDescriptors()->end(); ++desc)
348 if ((*desc)->getTag() == CA_DESCRIPTOR)
352 m_pmt_in_progress->second.scrambled = scrambled;
354 m_pmt_in_progress->second.serviceType = 1;
355 else if ( have_audio )
356 m_pmt_in_progress->second.serviceType = 2;
358 m_pmt_in_progress->second.serviceType = 100;
360 if (err == -2) // aborted in sdt progress
361 m_pmts_to_read.erase(m_pmt_in_progress++);
362 else if (m_pmt_running)
366 m_pmt_in_progress = m_pmts_to_read.begin();
367 m_pmt_running = true;
370 if (m_pmt_in_progress != m_pmts_to_read.end())
371 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first));
374 m_pmt_running = false;
380 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
382 /* add it to the list of known channels. */
384 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
387 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
389 /* check if we don't already have that channel ... */
392 feparm->getSystem(type);
396 case iDVBFrontend::feSatellite:
398 eDVBFrontendParametersSatellite parm;
399 feparm->getDVBS(parm);
400 SCAN_eDebug("try to add %d %d %d %d %d %d",
401 parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
404 case iDVBFrontend::feCable:
406 eDVBFrontendParametersCable parm;
407 feparm->getDVBC(parm);
408 SCAN_eDebug("try to add %d %d %d %d",
409 parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
412 case iDVBFrontend::feTerrestrial:
414 eDVBFrontendParametersTerrestrial parm;
415 feparm->getDVBT(parm);
416 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
417 parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
418 parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
424 /* ... in the list of channels to scan */
425 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
427 if (sameChannel(*i, feparm))
431 *i = feparm; // update
432 SCAN_eDebug("update");
436 SCAN_eDebug("remove dupe");
437 m_ch_toScan.erase(i++);
447 SCAN_eDebug("already in todo list");
451 /* ... in the list of successfully scanned channels */
452 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
453 if (sameChannel(*i, feparm))
455 SCAN_eDebug("successfully scanned");
459 /* ... in the list of unavailable channels */
460 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
461 if (sameChannel(*i, feparm, true))
463 SCAN_eDebug("scanned but not available");
467 /* ... on the current channel */
468 if (sameChannel(m_ch_current, feparm))
470 SCAN_eDebug("is current");
474 SCAN_eDebug("really add");
475 /* otherwise, add it to the todo list. */
476 m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
479 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
482 if (ch1->calculateDifference(ch2, diff, exact))
484 if (diff < 4000) // more than 4mhz difference?
489 void eDVBScan::channelDone()
491 if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
493 unsigned long hash = 0;
495 // m_ch_current is not set, when eDVBScan is just used for a SDT update
498 unsigned int channelFlags;
499 m_channel->getCurrentFrontendParameters(m_ch_current);
500 m_ch_current->getFlags(channelFlags);
501 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
502 m_flags |= scanOnlyFree;
505 m_ch_current->getHash(hash);
507 eDVBNamespace dvbnamespace = buildNamespace(
508 (**m_SDT->getSections().begin()).getOriginalNetworkId(),
509 (**m_SDT->getSections().begin()).getTransportStreamId(),
512 SCAN_eDebug("SDT: ");
513 std::vector<ServiceDescriptionSection*>::const_iterator i;
514 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
515 processSDT(dvbnamespace, **i);
516 m_ready &= ~validSDT;
519 if (m_ready & validNIT)
522 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
523 m_ch_current->getSystem(system);
524 SCAN_eDebug("dumping NIT");
525 if (m_flags & clearToScanOnFirstNIT)
527 m_ch_toScan_backup = m_ch_toScan;
530 std::vector<NetworkInformationSection*>::const_iterator i;
531 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
533 const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
535 for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin());
536 tsinfo != tsinfovec.end(); ++tsinfo)
538 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
539 (*tsinfo)->getOriginalNetworkId());
541 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
542 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
544 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
545 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
547 switch ((*desc)->getTag())
549 case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
551 if (system != iDVBFrontend::feCable)
552 break; // when current locked transponder is no cable transponder ignore this descriptor
553 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
554 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
555 eDVBFrontendParametersCable cable;
557 feparm->setDVBC(cable);
559 unsigned long hash=0;
560 feparm->getHash(hash);
561 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
564 eDVBChannelID(ns, tsid, onid),
568 case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
570 if (system != iDVBFrontend::feTerrestrial)
571 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
572 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
573 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
574 eDVBFrontendParametersTerrestrial terr;
576 feparm->setDVBT(terr);
578 unsigned long hash=0;
579 feparm->getHash(hash);
580 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
583 eDVBChannelID(ns, tsid, onid),
587 case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
589 if (system != iDVBFrontend::feSatellite)
590 break; // when current locked transponder is no satellite transponder ignore this descriptor
592 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
593 if (d.getFrequency() < 10000)
596 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
597 eDVBFrontendParametersSatellite sat;
600 eDVBFrontendParametersSatellite p;
601 m_ch_current->getDVBS(p);
603 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
604 sat.orbital_position = p.orbital_position;
606 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
608 SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
609 sat.orbital_position = p.orbital_position;
612 feparm->setDVBS(sat);
614 if ( p.orbital_position != sat.orbital_position)
615 SCAN_eDebug("dropping this transponder, it's on another satellite.");
618 unsigned long hash=0;
619 feparm->getHash(hash);
621 eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
627 SCAN_eDebug("descr<%x>", (*desc)->getTag());
635 /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
636 no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
639 This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
641 if (m_flags & clearToScanOnFirstNIT)
643 if (m_ch_toScan.empty())
645 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
646 m_ch_toScan = m_ch_toScan_backup;
648 m_flags &= ~clearToScanOnFirstNIT;
650 m_ready &= ~validNIT;
653 if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
655 if (m_abort_current_pmt)
657 m_abort_current_pmt = false;
663 SCAN_eDebug("channel done!");
665 /* if we had services on this channel, we declare
666 this channels as "known good". add it.
668 (TODO: not yet implemented)
669 a NIT entry could have possible overridden
670 our frontend data with more exact data.
672 (TODO: not yet implemented)
673 the tuning process could have lead to more
674 exact data than the user entered.
676 The channel id was probably corrected
677 by the data written in the SDT. this is
678 important, as "initial transponder lists"
679 usually don't have valid CHIDs (and that's
682 These are the reasons for adding the transponder
683 here, and not before.
686 for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
689 eServiceReferenceDVB ref;
690 ePtr<eDVBService> service = new eDVBService;
694 unsigned long hash = 0;
696 // m_ch_current is not set, when eDVBScan is just used for a SDT update
699 unsigned int channelFlags;
700 m_channel->getCurrentFrontendParameters(m_ch_current);
701 m_ch_current->getFlags(channelFlags);
702 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
703 m_flags |= scanOnlyFree;
706 m_ch_current->getHash(hash);
708 m_chid_current = eDVBChannelID(
709 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
710 m_pat_tsid, eOriginalNetworkID(0));
713 if (m_pmt_in_progress->second.serviceType == 1)
714 SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
715 else if (m_pmt_in_progress->second.serviceType == 2)
716 SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
718 SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
720 ref.set(m_chid_current);
721 ref.setServiceID(m_pmt_in_progress->first);
722 ref.setServiceType(m_pmt_in_progress->second.serviceType);
724 if (!m_ch_current->getSystem(type))
728 memset(pname, 0, sizeof(pname));
729 memset(sname, 0, sizeof(sname));
732 case iDVBFrontend::feSatellite:
734 eDVBFrontendParametersSatellite parm;
735 m_ch_current->getDVBS(parm);
736 snprintf(sname, 255, "%d%c SID 0x%02x",
738 parm.polarisation ? 'V' : 'H',
739 m_pmt_in_progress->first);
740 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
741 parm.system ? "DVB-S2" : "DVB-S",
742 parm.modulation == 1 ? "QPSK" : "8PSK",
744 parm.polarisation ? 'V' : 'H',
745 parm.orbital_position/10,
746 parm.orbital_position%10,
747 parm.orbital_position > 0 ? 'E' : 'W');
750 case iDVBFrontend::feTerrestrial:
752 eDVBFrontendParametersTerrestrial parm;
753 m_ch_current->getDVBT(parm);
754 snprintf(sname, 255, "%d SID 0x%02x",
756 m_pmt_in_progress->first);
759 case iDVBFrontend::feCable:
761 eDVBFrontendParametersCable parm;
762 m_ch_current->getDVBC(parm);
763 snprintf(sname, 255, "%d SID 0x%02x",
765 m_pmt_in_progress->first);
769 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
770 service->m_service_name = convertDVBUTF8(sname);
771 service->genSortName();
772 service->m_provider_name = pname;
775 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
779 m_last_service = i.first;
780 m_event(evtNewService);
782 m_pmts_to_read.erase(m_pmt_in_progress++);
786 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
788 addKnownGoodChannel(m_chid_current, m_ch_current);
790 m_ch_scanned.push_back(m_ch_current);
792 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
794 if (sameChannel(*i, m_ch_current))
796 SCAN_eDebug("remove dupe 2");
797 m_ch_toScan.erase(i++);
806 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
810 m_ch_scanned.clear();
811 m_ch_unavailable.clear();
812 m_new_channels.clear();
813 m_new_services.clear();
814 m_last_service = m_new_services.end();
816 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
819 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
821 if (sameChannel(*i, *ii, true))
828 m_ch_toScan.push_back(*i);
834 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
836 if (m_flags & scanRemoveServices)
838 bool clearTerrestrial=false;
839 bool clearCable=false;
840 std::set<unsigned int> scanned_sat_positions;
842 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
843 for (;it != m_ch_scanned.end(); ++it)
845 if (m_flags & scanDontRemoveUnscanned)
846 db->removeServices(&(*(*it)));
850 (*it)->getSystem(system);
853 case iDVBFrontend::feSatellite:
855 eDVBFrontendParametersSatellite sat_parm;
856 (*it)->getDVBS(sat_parm);
857 scanned_sat_positions.insert(sat_parm.orbital_position);
860 case iDVBFrontend::feTerrestrial:
862 clearTerrestrial=true;
865 case iDVBFrontend::feCable:
874 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
876 if (m_flags & scanDontRemoveUnscanned)
877 db->removeServices(&(*(*it)));
881 (*it)->getSystem(system);
884 case iDVBFrontend::feSatellite:
886 eDVBFrontendParametersSatellite sat_parm;
887 (*it)->getDVBS(sat_parm);
888 scanned_sat_positions.insert(sat_parm.orbital_position);
891 case iDVBFrontend::feTerrestrial:
893 clearTerrestrial=true;
896 case iDVBFrontend::feCable:
905 if (clearTerrestrial)
908 chid.dvbnamespace=0xEEEE0000;
909 db->removeServices(chid);
914 chid.dvbnamespace=0xFFFF0000;
915 db->removeServices(chid);
917 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
920 if (m_flags & scanDontRemoveFeeds)
921 chid.dvbnamespace = eDVBNamespace((*x)<<16);
922 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
923 db->removeServices(chid, *x);
927 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
928 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
930 if (m_flags & scanOnlyFree)
932 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
933 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
935 db->addChannelToList(ch->first, ch->second);
938 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
939 service(m_new_services.begin()); service != m_new_services.end(); ++service)
941 ePtr<eDVBService> dvb_service;
942 if (!db->getService(service->first, dvb_service))
944 if (dvb_service->m_flags & eDVBService::dxNoSDT)
946 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
948 dvb_service->m_service_name = service->second->m_service_name;
949 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
951 dvb_service->m_provider_name = service->second->m_provider_name;
952 if (service->second->m_ca.size())
953 dvb_service->m_ca = service->second->m_ca;
954 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
955 dvb_service->m_flags &= ~eDVBService::dxNewFound;
959 db->addService(service->first, service->second);
960 if (!(m_flags & scanRemoveServices))
961 service->second->m_flags |= eDVBService::dxNewFound;
966 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
968 const ServiceDescriptionList &services = *sdt.getDescriptions();
969 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
970 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
972 /* save correct CHID for this channel */
973 m_chid_current = chid;
975 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
977 unsigned short service_id = (*s)->getServiceId();
978 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
981 if (m_flags & scanOnlyFree)
983 std::map<unsigned short, service>::iterator it =
984 m_pmts_to_read.find(service_id);
985 if (it != m_pmts_to_read.end())
987 if (it->second.scrambled)
989 SCAN_eDebug("is scrambled!");
994 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
999 eServiceReferenceDVB ref;
1000 ePtr<eDVBService> service = new eDVBService;
1003 ref.setServiceID(service_id);
1005 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1006 desc != (*s)->getDescriptors()->end(); ++desc)
1008 switch ((*desc)->getTag())
1010 case SERVICE_DESCRIPTOR:
1012 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1013 ref.setServiceType(d.getServiceType());
1014 service->m_service_name = convertDVBUTF8(d.getServiceName());
1015 service->genSortName();
1017 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1018 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1021 case CA_IDENTIFIER_DESCRIPTOR:
1023 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1024 const CaSystemIdList &caids = *d.getCaSystemIds();
1025 SCAN_eDebugNoNewLine("CA ");
1026 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1028 SCAN_eDebugNoNewLine("%04x ", *i);
1029 service->m_ca.push_front(*i);
1035 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1040 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1044 m_last_service = i.first;
1045 m_event(evtNewService);
1048 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1049 m_abort_current_pmt = true;
1051 m_pmts_to_read.erase(service_id);
1057 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1059 connection = new eConnection(this, m_event.connect(event));
1063 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1065 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1066 transponders_total = m_ch_toScan.size() + transponders_done;
1067 services = m_new_services.size();
1070 void eDVBScan::getLastServiceName(std::string &last_service_name)
1072 if (m_last_service == m_new_services.end())
1073 last_service_name = "";
1075 last_service_name = m_last_service->second->m_service_name;
1078 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1081 return m_channel->getFrontend(fe);
1086 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)