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 #define SCAN_eDebug(x...) do { if (m_scan_debug) eDebug(x); } while(0)
17 #define SCAN_eDebugNoNewLine(x...) do { if (m_scan_debug) eDebugNoNewLine(x); } while(0)
21 eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug)
22 :m_channel(channel), m_channel_state(iDVBChannel::state_idle)
23 ,m_ready(0), m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT)
24 ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0)
25 ,m_usePAT(usePAT), m_scan_debug(debug)
27 if (m_channel->getDemux(m_demux))
28 SCAN_eDebug("scan: failed to allocate demux!");
29 m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
36 int eDVBScan::isValidONIDTSID(int orbital_position, eOriginalNetworkID onid, eTransportStreamID tsid)
43 case 0x13E: // workaround for 11258H and 11470V on hotbird with same ONID/TSID (0x13E/0x578)
44 return orbital_position != 130 || tsid != 0x578;
46 return orbital_position == 192;
48 return tsid != 0x00B0;
50 return tsid != 0x4321;
52 return abs(orbital_position-282) < 6;
54 return onid.get() < 0xFF00;
58 eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash)
60 // on valid ONIDs, ignore frequency ("sub network") part
61 if (isValidONIDTSID((hash >> 16) & 0xFFFF, onid, tsid))
63 return eDVBNamespace(hash);
66 void eDVBScan::stateChange(iDVBChannel *ch)
69 if (ch->getState(state))
71 if (m_channel_state == state)
74 if (state == iDVBChannel::state_ok)
77 m_channel_state = state;
78 } else if (state == iDVBChannel::state_failed)
80 m_ch_unavailable.push_back(m_ch_current);
83 /* unavailable will timeout, anyway. */
86 RESULT eDVBScan::nextChannel()
88 ePtr<iDVBFrontend> fe;
90 m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0;
94 m_pat_tsid = eTransportStreamID();
96 /* check what we need */
97 m_ready_all = readySDT;
99 if (m_flags & scanNetworkSearch)
100 m_ready_all |= readyNIT;
102 if (m_flags & scanSearchBAT)
103 m_ready_all |= readyBAT;
106 m_ready_all |= readyPAT;
108 if (m_ch_toScan.empty())
110 SCAN_eDebug("no channels left to scan.");
111 SCAN_eDebug("%d channels scanned, %d were unavailable.",
112 m_ch_scanned.size(), m_ch_unavailable.size());
113 SCAN_eDebug("%d channels in database.", m_new_channels.size());
118 m_ch_current = m_ch_toScan.front();
120 m_ch_toScan.pop_front();
122 if (m_channel->getFrontend(fe))
128 m_chid_current = eDVBChannelID();
130 m_channel_state = iDVBChannel::state_idle;
132 if (fe->tune(*m_ch_current))
133 return nextChannel();
139 RESULT eDVBScan::startFilter()
144 /* only start required filters filter */
146 if (m_ready_all & readyPAT)
147 startSDT = m_ready & readyPAT;
149 // m_ch_current is not set, when eDVBScan is just used for a SDT update
152 unsigned int channelFlags;
153 m_channel->getCurrentFrontendParameters(m_ch_current);
154 m_ch_current->getFlags(channelFlags);
155 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
156 m_flags |= scanOnlyFree;
160 if (startSDT && (m_ready_all & readySDT))
162 m_SDT = new eTable<ServiceDescriptionSection>(m_scan_debug);
164 if (m_ready & readyPAT && m_ready & validPAT)
166 std::vector<ProgramAssociationSection*>::const_iterator i =
167 m_PAT->getSections().begin();
168 ASSERT(i != m_PAT->getSections().end());
169 tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
170 m_pat_tsid = eTransportStreamID(tsid);
171 for (; i != m_PAT->getSections().end(); ++i)
173 const ProgramAssociationSection &pat = **i;
174 ProgramAssociationConstIterator program = pat.getPrograms()->begin();
175 for (; program != pat.getPrograms()->end(); ++program)
176 m_pmts_to_read.insert(std::pair<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
178 m_PMT = new eTable<ProgramMapSection>(m_scan_debug);
179 CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
181 // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
185 m_ch_current->getSystem(type);
186 if (type == iDVBFrontend::feCable)
188 eDVBFrontendParametersCable parm;
189 m_ch_current->getDVBC(parm);
190 if ((tsid == 0x00d7 && abs(parm.frequency-618000) < 2000) ||
191 (tsid == 0x00d8 && abs(parm.frequency-626000) < 2000))
198 if (m_SDT->start(m_demux, eDVBSDTSpec()))
201 else if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
203 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
206 if (!(m_ready & readyPAT))
209 if (m_ready_all & readyPAT)
211 m_PAT = new eTable<ProgramAssociationSection>(m_scan_debug);
212 if (m_PAT->start(m_demux, eDVBPATSpec(4000)))
214 CONNECT(m_PAT->tableReady, eDVBScan::PATready);
218 if (m_ready_all & readyNIT)
220 m_NIT = new eTable<NetworkInformationSection>(m_scan_debug);
221 if (m_NIT->start(m_demux, eDVBNITSpec()))
223 CONNECT(m_NIT->tableReady, eDVBScan::NITready);
227 if (m_ready_all & readyBAT)
229 m_BAT = new eTable<BouquetAssociationSection>(m_scan_debug);
230 if (m_BAT->start(m_demux, eDVBBATSpec()))
232 CONNECT(m_BAT->tableReady, eDVBScan::BATready);
238 void eDVBScan::SDTready(int err)
240 SCAN_eDebug("got sdt %d", err);
247 void eDVBScan::NITready(int err)
249 SCAN_eDebug("got nit, err %d", err);
256 void eDVBScan::BATready(int err)
258 SCAN_eDebug("got bat");
265 void eDVBScan::PATready(int err)
267 SCAN_eDebug("got pat");
271 startFilter(); // for starting the SDT filter
274 void eDVBScan::PMTready(int err)
276 SCAN_eDebug("got pmt %d", err);
279 bool scrambled = false;
280 bool have_audio = false;
281 bool have_video = false;
282 unsigned short pcrpid = 0xFFFF;
283 std::vector<ProgramMapSection*>::const_iterator i;
285 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
287 const ProgramMapSection &pmt = **i;
288 if (pcrpid == 0xFFFF)
289 pcrpid = pmt.getPcrPid();
291 SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
292 ElementaryStreamInfoConstIterator es;
293 for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
295 int isaudio = 0, isvideo = 0, is_scrambled = 0;
296 switch ((*es)->getType())
298 case 0xEA: // TS_PSI_ST_SMPTE_VC1
299 case 0x1b: // AVC Video Stream (MPEG4 H264)
300 case 0x10: // MPEG 4 Part 2
301 case 0x01: // MPEG 1 video
302 case 0x02: // MPEG 2 video
304 //break; fall through !!!
305 case 0x03: // MPEG 1 audio
306 case 0x04: // MPEG 2 audio
307 case 0x0f: // MPEG 2 AAC
308 case 0x11: // MPEG 4 AAC
311 case 0x06: // PES Private
312 case 0x81: // user private
313 for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
314 desc != (*es)->getDescriptors()->end(); ++desc)
316 uint8_t tag = (*desc)->getTag();
317 if (!isaudio && !isvideo)
319 /* PES private can contain AC-3, DTS or lots of other stuff.
320 check descriptors to get the exakt type. */
323 case 0x1C: // TS_PSI_DT_MPEG4_Audio
324 case 0x2B: // TS_PSI_DT_MPEG2_AAC
328 case AUDIO_STREAM_DESCRIPTOR:
331 case 0x28: // TS_PSI_DT_AVC
332 case 0x1B: // TS_PSI_DT_MPEG4_Video
333 case VIDEO_STREAM_DESCRIPTOR:
336 case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
338 /* libdvbsi++ doesn't yet support this descriptor type, so work around. */
339 if ((*desc)->getLength() < 4)
341 unsigned char descr[6];
342 (*desc)->writeToBuffer(descr);
343 int format_identifier = (descr[2] << 24) | (descr[3] << 16) | (descr[4] << 8) | (descr[5]);
344 switch (format_identifier)
346 case 0x41432d33: // == 'AC-3'
347 case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
348 case 0x42535344: // == 'BSSD' (LPCM)
351 case 0x56432d31: // == 'VC-1'
362 if (tag == CA_DESCRIPTOR)
376 for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
377 desc != pmt.getDescriptors()->end(); ++desc)
379 if ((*desc)->getTag() == CA_DESCRIPTOR)
383 m_pmt_in_progress->second.scrambled = scrambled;
385 m_pmt_in_progress->second.serviceType = 1;
386 else if ( have_audio )
387 m_pmt_in_progress->second.serviceType = 2;
389 m_pmt_in_progress->second.serviceType = 100;
391 if (err == -1) // timeout or removed by sdt
392 m_pmts_to_read.erase(m_pmt_in_progress++);
393 else if (m_pmt_running)
397 m_pmt_in_progress = m_pmts_to_read.begin();
398 m_pmt_running = true;
401 if (m_pmt_in_progress != m_pmts_to_read.end())
402 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
406 m_pmt_running = false;
412 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
414 /* add it to the list of known channels. */
416 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
419 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
421 /* check if we don't already have that channel ... */
424 feparm->getSystem(type);
428 case iDVBFrontend::feSatellite:
430 eDVBFrontendParametersSatellite parm;
431 feparm->getDVBS(parm);
432 SCAN_eDebug("try to add %d %d %d %d %d %d",
433 parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
436 case iDVBFrontend::feCable:
438 eDVBFrontendParametersCable parm;
439 feparm->getDVBC(parm);
440 SCAN_eDebug("try to add %d %d %d %d",
441 parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
444 case iDVBFrontend::feTerrestrial:
446 eDVBFrontendParametersTerrestrial parm;
447 feparm->getDVBT(parm);
448 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
449 parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
450 parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
456 /* ... in the list of channels to scan */
457 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
459 if (sameChannel(*i, feparm))
463 *i = feparm; // update
464 SCAN_eDebug("update");
468 SCAN_eDebug("remove dupe");
469 m_ch_toScan.erase(i++);
479 SCAN_eDebug("already in todo list");
483 /* ... in the list of successfully scanned channels */
484 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
485 if (sameChannel(*i, feparm))
487 SCAN_eDebug("successfully scanned");
491 /* ... in the list of unavailable channels */
492 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
493 if (sameChannel(*i, feparm, true))
495 SCAN_eDebug("scanned but not available");
499 /* ... on the current channel */
500 if (sameChannel(m_ch_current, feparm))
502 SCAN_eDebug("is current");
506 SCAN_eDebug("really add");
507 /* otherwise, add it to the todo list. */
508 m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
511 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
514 if (ch1->calculateDifference(ch2, diff, exact))
516 if (diff < 4000) // more than 4mhz difference?
521 void eDVBScan::channelDone()
523 if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
525 unsigned long hash = 0;
527 m_ch_current->getHash(hash);
529 eDVBNamespace dvbnamespace = buildNamespace(
530 (**m_SDT->getSections().begin()).getOriginalNetworkId(),
531 (**m_SDT->getSections().begin()).getTransportStreamId(),
534 SCAN_eDebug("SDT: ");
535 std::vector<ServiceDescriptionSection*>::const_iterator i;
536 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
537 processSDT(dvbnamespace, **i);
538 m_ready &= ~validSDT;
541 if (m_ready & validNIT)
544 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
545 m_ch_current->getSystem(system);
546 SCAN_eDebug("dumping NIT");
547 if (m_flags & clearToScanOnFirstNIT)
549 m_ch_toScan_backup = m_ch_toScan;
552 std::vector<NetworkInformationSection*>::const_iterator i;
553 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
555 const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
557 for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin());
558 tsinfo != tsinfovec.end(); ++tsinfo)
560 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
561 (*tsinfo)->getOriginalNetworkId());
563 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
564 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
566 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
567 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
569 switch ((*desc)->getTag())
571 case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
573 if (system != iDVBFrontend::feCable)
574 break; // when current locked transponder is no cable transponder ignore this descriptor
575 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
576 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
577 eDVBFrontendParametersCable cable;
579 feparm->setDVBC(cable);
581 unsigned long hash=0;
582 feparm->getHash(hash);
583 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
586 eDVBChannelID(ns, tsid, onid),
590 case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
592 if (system != iDVBFrontend::feTerrestrial)
593 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
594 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
595 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
596 eDVBFrontendParametersTerrestrial terr;
598 feparm->setDVBT(terr);
600 unsigned long hash=0;
601 feparm->getHash(hash);
602 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
605 eDVBChannelID(ns, tsid, onid),
609 case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
611 if (system != iDVBFrontend::feSatellite)
612 break; // when current locked transponder is no satellite transponder ignore this descriptor
614 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
615 if (d.getFrequency() < 10000)
618 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
619 eDVBFrontendParametersSatellite sat;
622 eDVBFrontendParametersSatellite p;
623 m_ch_current->getDVBS(p);
625 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
626 sat.orbital_position = p.orbital_position;
628 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
630 SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
631 sat.orbital_position = p.orbital_position;
634 feparm->setDVBS(sat);
636 if ( p.orbital_position != sat.orbital_position)
637 SCAN_eDebug("dropping this transponder, it's on another satellite.");
640 unsigned long hash=0;
641 feparm->getHash(hash);
643 eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
649 SCAN_eDebug("descr<%x>", (*desc)->getTag());
657 /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
658 no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
661 This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
663 if (m_flags & clearToScanOnFirstNIT)
665 if (m_ch_toScan.empty())
667 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
668 m_ch_toScan = m_ch_toScan_backup;
670 m_flags &= ~clearToScanOnFirstNIT;
672 m_ready &= ~validNIT;
675 if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
677 if (m_abort_current_pmt)
679 m_abort_current_pmt = false;
685 SCAN_eDebug("channel done!");
687 /* if we had services on this channel, we declare
688 this channels as "known good". add it.
690 (TODO: not yet implemented)
691 a NIT entry could have possible overridden
692 our frontend data with more exact data.
694 (TODO: not yet implemented)
695 the tuning process could have lead to more
696 exact data than the user entered.
698 The channel id was probably corrected
699 by the data written in the SDT. this is
700 important, as "initial transponder lists"
701 usually don't have valid CHIDs (and that's
704 These are the reasons for adding the transponder
705 here, and not before.
708 for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
711 eServiceReferenceDVB ref;
712 ePtr<eDVBService> service = new eDVBService;
716 unsigned long hash = 0;
718 m_ch_current->getHash(hash);
720 m_chid_current = eDVBChannelID(
721 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
722 m_pat_tsid, eOriginalNetworkID(0));
725 if (m_pmt_in_progress->second.serviceType == 1)
726 SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
727 else if (m_pmt_in_progress->second.serviceType == 2)
728 SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
730 SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
732 ref.set(m_chid_current);
733 ref.setServiceID(m_pmt_in_progress->first);
734 ref.setServiceType(m_pmt_in_progress->second.serviceType);
736 if (!m_ch_current->getSystem(type))
740 memset(pname, 0, sizeof(pname));
741 memset(sname, 0, sizeof(sname));
744 case iDVBFrontend::feSatellite:
746 eDVBFrontendParametersSatellite parm;
747 m_ch_current->getDVBS(parm);
748 snprintf(sname, 255, "%d%c SID 0x%02x",
750 parm.polarisation ? 'V' : 'H',
751 m_pmt_in_progress->first);
752 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
753 parm.system ? "DVB-S2" : "DVB-S",
754 parm.modulation == 1 ? "QPSK" : "8PSK",
756 parm.polarisation ? 'V' : 'H',
757 parm.orbital_position/10,
758 parm.orbital_position%10,
759 parm.orbital_position > 0 ? 'E' : 'W');
762 case iDVBFrontend::feTerrestrial:
764 ePtr<iDVBFrontend> fe;
765 eDVBFrontendParametersTerrestrial parm;
766 m_ch_current->getDVBT(parm);
767 snprintf(sname, 255, "%d SID 0x%02x",
769 m_pmt_in_progress->first);
770 if (!m_channel->getFrontend(fe))
772 ePyObject tp_dict = PyDict_New();
773 fe->getTransponderData(tp_dict, false);
774 m_corrected_frequencys[m_chid_current] =
775 PyInt_AsLong(PyDict_GetItemString(tp_dict, "frequency"));
780 case iDVBFrontend::feCable:
782 eDVBFrontendParametersCable parm;
783 m_ch_current->getDVBC(parm);
784 snprintf(sname, 255, "%d SID 0x%02x",
786 m_pmt_in_progress->first);
790 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
791 service->m_service_name = convertDVBUTF8(sname);
792 service->genSortName();
793 service->m_provider_name = convertDVBUTF8(pname);
796 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
797 SCAN_eDebug("add not scrambled!");
798 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
799 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
802 m_last_service = i.first;
803 m_event(evtNewService);
807 SCAN_eDebug("dont add... is scrambled!");
808 m_pmts_to_read.erase(m_pmt_in_progress++);
812 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
814 addKnownGoodChannel(m_chid_current, m_ch_current);
816 m_ch_scanned.push_back(m_ch_current);
818 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
820 if (sameChannel(*i, m_ch_current))
822 SCAN_eDebug("remove dupe 2");
823 m_ch_toScan.erase(i++);
832 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
836 m_ch_scanned.clear();
837 m_ch_unavailable.clear();
838 m_new_channels.clear();
839 m_new_services.clear();
840 m_last_service = m_new_services.end();
842 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
845 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
847 if (sameChannel(*i, *ii, true))
854 m_ch_toScan.push_back(*i);
860 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
862 if (m_flags & scanRemoveServices)
864 bool clearTerrestrial=false;
865 bool clearCable=false;
866 std::set<unsigned int> scanned_sat_positions;
868 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
869 for (;it != m_ch_scanned.end(); ++it)
871 if (m_flags & scanDontRemoveUnscanned)
872 db->removeServices(&(*(*it)));
876 (*it)->getSystem(system);
879 case iDVBFrontend::feSatellite:
881 eDVBFrontendParametersSatellite sat_parm;
882 (*it)->getDVBS(sat_parm);
883 scanned_sat_positions.insert(sat_parm.orbital_position);
886 case iDVBFrontend::feTerrestrial:
888 clearTerrestrial=true;
891 case iDVBFrontend::feCable:
900 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
902 if (m_flags & scanDontRemoveUnscanned)
903 db->removeServices(&(*(*it)));
907 (*it)->getSystem(system);
910 case iDVBFrontend::feSatellite:
912 eDVBFrontendParametersSatellite sat_parm;
913 (*it)->getDVBS(sat_parm);
914 scanned_sat_positions.insert(sat_parm.orbital_position);
917 case iDVBFrontend::feTerrestrial:
919 clearTerrestrial=true;
922 case iDVBFrontend::feCable:
931 if (clearTerrestrial)
934 chid.dvbnamespace=0xEEEE0000;
935 db->removeServices(chid);
940 chid.dvbnamespace=0xFFFF0000;
941 db->removeServices(chid);
943 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
946 if (m_flags & scanDontRemoveFeeds)
947 chid.dvbnamespace = eDVBNamespace((*x)<<16);
948 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
949 db->removeServices(chid, *x);
953 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
954 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
957 ch->second->getSystem(system);
958 if (system == iDVBFrontend::feTerrestrial)
960 std::map<eDVBChannelID, unsigned int>::iterator it = m_corrected_frequencys.find(ch->first);
961 if (it != m_corrected_frequencys.end())
963 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
964 eDVBFrontendParametersTerrestrial parm;
966 eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
967 ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
968 ch->first.dvbnamespace.get(), it->second, parm.frequency);
969 parm.frequency = it->second;
971 m_corrected_frequencys.erase(it);
974 if (m_flags & scanOnlyFree)
976 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
977 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
979 db->addChannelToList(ch->first, ch->second);
982 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
983 service(m_new_services.begin()); service != m_new_services.end(); ++service)
985 ePtr<eDVBService> dvb_service;
986 if (!db->getService(service->first, dvb_service))
988 if (dvb_service->m_flags & eDVBService::dxNoSDT)
990 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
992 dvb_service->m_service_name = service->second->m_service_name;
993 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
995 dvb_service->m_provider_name = service->second->m_provider_name;
996 if (service->second->m_ca.size())
997 dvb_service->m_ca = service->second->m_ca;
998 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
999 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1003 db->addService(service->first, service->second);
1004 if (!(m_flags & scanRemoveServices))
1005 service->second->m_flags |= eDVBService::dxNewFound;
1010 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1012 const ServiceDescriptionList &services = *sdt.getDescriptions();
1013 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1014 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1016 /* save correct CHID for this channel */
1017 m_chid_current = chid;
1019 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1021 unsigned short service_id = (*s)->getServiceId();
1022 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1025 if (m_flags & scanOnlyFree)
1027 std::map<unsigned short, service>::iterator it =
1028 m_pmts_to_read.find(service_id);
1029 if (it != m_pmts_to_read.end())
1031 if (it->second.scrambled)
1033 SCAN_eDebug("is scrambled!");
1037 SCAN_eDebug("is free");
1040 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1047 eServiceReferenceDVB ref;
1048 ePtr<eDVBService> service = new eDVBService;
1051 ref.setServiceID(service_id);
1053 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1054 desc != (*s)->getDescriptors()->end(); ++desc)
1056 switch ((*desc)->getTag())
1058 case SERVICE_DESCRIPTOR:
1060 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1061 ref.setServiceType(d.getServiceType());
1062 service->m_service_name = convertDVBUTF8(d.getServiceName());
1063 service->genSortName();
1065 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1066 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1069 case CA_IDENTIFIER_DESCRIPTOR:
1071 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1072 const CaSystemIdList &caids = *d.getCaSystemIds();
1073 SCAN_eDebugNoNewLine("CA ");
1074 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1076 SCAN_eDebugNoNewLine("%04x ", *i);
1077 service->m_ca.push_front(*i);
1083 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1088 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1089 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1093 m_last_service = i.first;
1094 m_event(evtNewService);
1097 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1098 m_abort_current_pmt = true;
1100 m_pmts_to_read.erase(service_id);
1106 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1108 connection = new eConnection(this, m_event.connect(event));
1112 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1114 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1115 transponders_total = m_ch_toScan.size() + transponders_done;
1116 services = m_new_services.size();
1119 void eDVBScan::getLastServiceName(std::string &last_service_name)
1121 if (m_last_service == m_new_services.end())
1122 last_service_name = "";
1124 last_service_name = m_last_service->second->m_service_name;
1127 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1130 return m_channel->getFrontend(fe);
1135 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)