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 <dvbsi++/registration_descriptor.h>
9 #include <lib/dvb/specs.h>
10 #include <lib/dvb/esection.h>
11 #include <lib/dvb/scan.h>
12 #include <lib/dvb/frontend.h>
13 #include <lib/base/eerror.h>
14 #include <lib/base/estring.h>
17 #define SCAN_eDebug(x...) do { if (m_scan_debug) eDebug(x); } while(0)
18 #define SCAN_eDebugNoNewLine(x...) do { if (m_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)
26 ,m_usePAT(usePAT), m_scan_debug(debug)
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)
44 case 0x13E: // workaround for 11258H and 11470V on hotbird with same ONID/TSID (0x13E/0x578)
45 return orbital_position != 130 || tsid != 0x578;
47 return orbital_position == 192;
49 return tsid != 0x00B0;
51 return tsid != 0x4321;
53 return abs(orbital_position-282) < 6;
55 return onid.get() < 0xFF00;
59 eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash)
61 // on valid ONIDs, ignore frequency ("sub network") part
62 if (isValidONIDTSID((hash >> 16) & 0xFFFF, onid, tsid))
64 return eDVBNamespace(hash);
67 void eDVBScan::stateChange(iDVBChannel *ch)
70 if (ch->getState(state))
72 if (m_channel_state == state)
75 if (state == iDVBChannel::state_ok)
78 m_channel_state = state;
79 } else if (state == iDVBChannel::state_failed)
81 m_ch_unavailable.push_back(m_ch_current);
84 /* unavailable will timeout, anyway. */
87 RESULT eDVBScan::nextChannel()
89 ePtr<iDVBFrontend> fe;
91 m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0;
95 m_pat_tsid = eTransportStreamID();
97 /* check what we need */
98 m_ready_all = readySDT;
100 if (m_flags & scanNetworkSearch)
101 m_ready_all |= readyNIT;
103 if (m_flags & scanSearchBAT)
104 m_ready_all |= readyBAT;
107 m_ready_all |= readyPAT;
109 if (m_ch_toScan.empty())
111 SCAN_eDebug("no channels left to scan.");
112 SCAN_eDebug("%d channels scanned, %d were unavailable.",
113 m_ch_scanned.size(), m_ch_unavailable.size());
114 SCAN_eDebug("%d channels in database.", m_new_channels.size());
119 m_ch_current = m_ch_toScan.front();
121 m_ch_toScan.pop_front();
123 if (m_channel->getFrontend(fe))
129 m_chid_current = eDVBChannelID();
131 m_channel_state = iDVBChannel::state_idle;
133 if (fe->tune(*m_ch_current))
134 return nextChannel();
140 RESULT eDVBScan::startFilter()
145 /* only start required filters filter */
147 if (m_ready_all & readyPAT)
148 startSDT = m_ready & readyPAT;
150 // m_ch_current is not set, when eDVBScan is just used for a SDT update
153 unsigned int channelFlags;
154 m_channel->getCurrentFrontendParameters(m_ch_current);
155 m_ch_current->getFlags(channelFlags);
156 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
157 m_flags |= scanOnlyFree;
161 if (startSDT && (m_ready_all & readySDT))
163 m_SDT = new eTable<ServiceDescriptionSection>(m_scan_debug);
165 if (m_ready & readyPAT && m_ready & validPAT)
167 std::vector<ProgramAssociationSection*>::const_iterator i =
168 m_PAT->getSections().begin();
169 ASSERT(i != m_PAT->getSections().end());
170 tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
171 m_pat_tsid = eTransportStreamID(tsid);
172 for (; i != m_PAT->getSections().end(); ++i)
174 const ProgramAssociationSection &pat = **i;
175 ProgramAssociationConstIterator program = pat.getPrograms()->begin();
176 for (; program != pat.getPrograms()->end(); ++program)
177 m_pmts_to_read.insert(std::pair<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
179 m_PMT = new eTable<ProgramMapSection>(m_scan_debug);
180 CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
182 // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
186 m_ch_current->getSystem(type);
187 if (type == iDVBFrontend::feCable)
189 eDVBFrontendParametersCable parm;
190 m_ch_current->getDVBC(parm);
191 if ((tsid == 0x00d7 && abs(parm.frequency-618000) < 2000) ||
192 (tsid == 0x00d8 && abs(parm.frequency-626000) < 2000))
199 if (m_SDT->start(m_demux, eDVBSDTSpec()))
202 else if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
204 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
207 if (!(m_ready & readyPAT))
210 if (m_ready_all & readyPAT)
212 m_PAT = new eTable<ProgramAssociationSection>(m_scan_debug);
213 if (m_PAT->start(m_demux, eDVBPATSpec(4000)))
215 CONNECT(m_PAT->tableReady, eDVBScan::PATready);
219 if (m_ready_all & readyNIT)
221 m_NIT = new eTable<NetworkInformationSection>(m_scan_debug);
222 if (m_NIT->start(m_demux, eDVBNITSpec()))
224 CONNECT(m_NIT->tableReady, eDVBScan::NITready);
228 if (m_ready_all & readyBAT)
230 m_BAT = new eTable<BouquetAssociationSection>(m_scan_debug);
231 if (m_BAT->start(m_demux, eDVBBATSpec()))
233 CONNECT(m_BAT->tableReady, eDVBScan::BATready);
239 void eDVBScan::SDTready(int err)
241 SCAN_eDebug("got sdt %d", err);
248 void eDVBScan::NITready(int err)
250 SCAN_eDebug("got nit, err %d", err);
257 void eDVBScan::BATready(int err)
259 SCAN_eDebug("got bat");
266 void eDVBScan::PATready(int err)
268 SCAN_eDebug("got pat");
272 startFilter(); // for starting the SDT filter
275 void eDVBScan::PMTready(int err)
277 SCAN_eDebug("got pmt %d", err);
280 bool scrambled = false;
281 bool have_audio = false;
282 bool have_video = false;
283 unsigned short pcrpid = 0xFFFF;
284 std::vector<ProgramMapSection*>::const_iterator i;
286 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
288 const ProgramMapSection &pmt = **i;
289 if (pcrpid == 0xFFFF)
290 pcrpid = pmt.getPcrPid();
292 SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
293 ElementaryStreamInfoConstIterator es;
294 for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
296 int isaudio = 0, isvideo = 0, is_scrambled = 0, forced_audio = 0, forced_video = 0;
297 switch ((*es)->getType())
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
305 //break; fall through !!!
306 case 0x03: // MPEG 1 audio
307 case 0x04: // MPEG 2 audio
308 case 0x0f: // MPEG 2 AAC
309 case 0x11: // MPEG 4 AAC
315 case 0x06: // PES Private
316 case 0x81: // user private
317 case 0xEA: // TS_PSI_ST_SMPTE_VC1
318 for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
319 desc != (*es)->getDescriptors()->end(); ++desc)
321 uint8_t tag = (*desc)->getTag();
322 /* PES private can contain AC-3, DTS or lots of other stuff.
323 check descriptors to get the exakt type. */
324 if (!forced_video && !forced_audio)
328 case 0x1C: // TS_PSI_DT_MPEG4_Audio
329 case 0x2B: // TS_PSI_DT_MPEG2_AAC
333 case AUDIO_STREAM_DESCRIPTOR:
336 case 0x28: // TS_PSI_DT_AVC
337 case 0x1B: // TS_PSI_DT_MPEG4_Video
338 case VIDEO_STREAM_DESCRIPTOR:
341 case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
343 RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc);
344 switch (d->getFormatIdentifier())
346 case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
347 case 0x41432d33: // == 'AC-3'
348 case 0x42535344: // == 'BSSD' (LPCM)
351 case 0x56432d31: // == 'VC-1'
362 if (tag == CA_DESCRIPTOR)
377 for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
378 desc != pmt.getDescriptors()->end(); ++desc)
380 if ((*desc)->getTag() == CA_DESCRIPTOR)
384 m_pmt_in_progress->second.scrambled = scrambled;
386 m_pmt_in_progress->second.serviceType = 1;
387 else if ( have_audio )
388 m_pmt_in_progress->second.serviceType = 2;
390 m_pmt_in_progress->second.serviceType = 100;
392 if (err == -1) // timeout or removed by sdt
393 m_pmts_to_read.erase(m_pmt_in_progress++);
394 else if (m_pmt_running)
398 m_pmt_in_progress = m_pmts_to_read.begin();
399 m_pmt_running = true;
402 if (m_pmt_in_progress != m_pmts_to_read.end())
403 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
407 m_pmt_running = false;
413 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
415 /* add it to the list of known channels. */
417 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
420 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
422 /* check if we don't already have that channel ... */
425 feparm->getSystem(type);
429 case iDVBFrontend::feSatellite:
431 eDVBFrontendParametersSatellite parm;
432 feparm->getDVBS(parm);
433 SCAN_eDebug("try to add %d %d %d %d %d %d",
434 parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
437 case iDVBFrontend::feCable:
439 eDVBFrontendParametersCable parm;
440 feparm->getDVBC(parm);
441 SCAN_eDebug("try to add %d %d %d %d",
442 parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
445 case iDVBFrontend::feTerrestrial:
447 eDVBFrontendParametersTerrestrial parm;
448 feparm->getDVBT(parm);
449 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
450 parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
451 parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
457 /* ... in the list of channels to scan */
458 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
460 if (sameChannel(*i, feparm))
464 *i = feparm; // update
465 SCAN_eDebug("update");
469 SCAN_eDebug("remove dupe");
470 m_ch_toScan.erase(i++);
480 SCAN_eDebug("already in todo list");
484 /* ... in the list of successfully scanned channels */
485 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
486 if (sameChannel(*i, feparm))
488 SCAN_eDebug("successfully scanned");
492 /* ... in the list of unavailable channels */
493 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
494 if (sameChannel(*i, feparm, true))
496 SCAN_eDebug("scanned but not available");
500 /* ... on the current channel */
501 if (sameChannel(m_ch_current, feparm))
503 SCAN_eDebug("is current");
507 SCAN_eDebug("really add");
508 /* otherwise, add it to the todo list. */
509 m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
512 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
515 if (ch1->calculateDifference(ch2, diff, exact))
517 if (diff < 4000) // more than 4mhz difference?
522 void eDVBScan::channelDone()
524 if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
526 unsigned long hash = 0;
528 m_ch_current->getHash(hash);
530 eDVBNamespace dvbnamespace = buildNamespace(
531 (**m_SDT->getSections().begin()).getOriginalNetworkId(),
532 (**m_SDT->getSections().begin()).getTransportStreamId(),
535 SCAN_eDebug("SDT: ");
536 std::vector<ServiceDescriptionSection*>::const_iterator i;
537 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
538 processSDT(dvbnamespace, **i);
539 m_ready &= ~validSDT;
542 if (m_ready & validNIT)
545 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
546 m_ch_current->getSystem(system);
547 SCAN_eDebug("dumping NIT");
548 if (m_flags & clearToScanOnFirstNIT)
550 m_ch_toScan_backup = m_ch_toScan;
553 std::vector<NetworkInformationSection*>::const_iterator i;
554 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
556 const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
558 for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin());
559 tsinfo != tsinfovec.end(); ++tsinfo)
561 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
562 (*tsinfo)->getOriginalNetworkId());
564 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
565 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
567 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
568 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
570 switch ((*desc)->getTag())
572 case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
574 if (system != iDVBFrontend::feCable)
575 break; // when current locked transponder is no cable transponder ignore this descriptor
576 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
577 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
578 eDVBFrontendParametersCable cable;
580 feparm->setDVBC(cable);
582 unsigned long hash=0;
583 feparm->getHash(hash);
584 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
587 eDVBChannelID(ns, tsid, onid),
591 case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
593 if (system != iDVBFrontend::feTerrestrial)
594 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
595 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
596 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
597 eDVBFrontendParametersTerrestrial terr;
599 feparm->setDVBT(terr);
601 unsigned long hash=0;
602 feparm->getHash(hash);
603 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
606 eDVBChannelID(ns, tsid, onid),
610 case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
612 if (system != iDVBFrontend::feSatellite)
613 break; // when current locked transponder is no satellite transponder ignore this descriptor
615 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
616 if (d.getFrequency() < 10000)
619 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
620 eDVBFrontendParametersSatellite sat;
623 eDVBFrontendParametersSatellite p;
624 m_ch_current->getDVBS(p);
626 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
627 sat.orbital_position = p.orbital_position;
629 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
631 SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
632 sat.orbital_position = p.orbital_position;
635 feparm->setDVBS(sat);
637 if ( p.orbital_position != sat.orbital_position)
638 SCAN_eDebug("dropping this transponder, it's on another satellite.");
641 unsigned long hash=0;
642 feparm->getHash(hash);
644 eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
650 SCAN_eDebug("descr<%x>", (*desc)->getTag());
658 /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
659 no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
662 This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
664 if (m_flags & clearToScanOnFirstNIT)
666 if (m_ch_toScan.empty())
668 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
669 m_ch_toScan = m_ch_toScan_backup;
671 m_flags &= ~clearToScanOnFirstNIT;
673 m_ready &= ~validNIT;
676 if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
678 if (m_abort_current_pmt)
680 m_abort_current_pmt = false;
686 SCAN_eDebug("channel done!");
688 /* if we had services on this channel, we declare
689 this channels as "known good". add it.
691 (TODO: not yet implemented)
692 a NIT entry could have possible overridden
693 our frontend data with more exact data.
695 (TODO: not yet implemented)
696 the tuning process could have lead to more
697 exact data than the user entered.
699 The channel id was probably corrected
700 by the data written in the SDT. this is
701 important, as "initial transponder lists"
702 usually don't have valid CHIDs (and that's
705 These are the reasons for adding the transponder
706 here, and not before.
709 for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
712 eServiceReferenceDVB ref;
713 ePtr<eDVBService> service = new eDVBService;
717 unsigned long hash = 0;
719 m_ch_current->getHash(hash);
721 m_chid_current = eDVBChannelID(
722 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
723 m_pat_tsid, eOriginalNetworkID(0));
726 if (m_pmt_in_progress->second.serviceType == 1)
727 SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
728 else if (m_pmt_in_progress->second.serviceType == 2)
729 SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
731 SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
733 ref.set(m_chid_current);
734 ref.setServiceID(m_pmt_in_progress->first);
735 ref.setServiceType(m_pmt_in_progress->second.serviceType);
737 if (!m_ch_current->getSystem(type))
741 memset(pname, 0, sizeof(pname));
742 memset(sname, 0, sizeof(sname));
745 case iDVBFrontend::feSatellite:
747 eDVBFrontendParametersSatellite parm;
748 m_ch_current->getDVBS(parm);
749 snprintf(sname, 255, "%d%c SID 0x%02x",
751 parm.polarisation ? 'V' : 'H',
752 m_pmt_in_progress->first);
753 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
754 parm.system ? "DVB-S2" : "DVB-S",
755 parm.modulation == 1 ? "QPSK" : "8PSK",
757 parm.polarisation ? 'V' : 'H',
758 parm.orbital_position/10,
759 parm.orbital_position%10,
760 parm.orbital_position > 0 ? 'E' : 'W');
763 case iDVBFrontend::feTerrestrial:
765 ePtr<iDVBFrontend> fe;
766 eDVBFrontendParametersTerrestrial parm;
767 m_ch_current->getDVBT(parm);
768 snprintf(sname, 255, "%d SID 0x%02x",
770 m_pmt_in_progress->first);
771 if (!m_channel->getFrontend(fe))
773 ePyObject tp_dict = PyDict_New();
774 fe->getTransponderData(tp_dict, false);
775 m_corrected_frequencys[m_chid_current] =
776 PyInt_AsLong(PyDict_GetItemString(tp_dict, "frequency"));
781 case iDVBFrontend::feCable:
783 eDVBFrontendParametersCable parm;
784 m_ch_current->getDVBC(parm);
785 snprintf(sname, 255, "%d SID 0x%02x",
787 m_pmt_in_progress->first);
791 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
792 service->m_service_name = convertDVBUTF8(sname);
793 service->genSortName();
794 service->m_provider_name = convertDVBUTF8(pname);
797 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
798 SCAN_eDebug("add not scrambled!");
799 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
800 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
803 m_last_service = i.first;
804 m_event(evtNewService);
808 SCAN_eDebug("dont add... is scrambled!");
809 m_pmts_to_read.erase(m_pmt_in_progress++);
813 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
815 addKnownGoodChannel(m_chid_current, m_ch_current);
817 m_ch_scanned.push_back(m_ch_current);
819 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
821 if (sameChannel(*i, m_ch_current))
823 SCAN_eDebug("remove dupe 2");
824 m_ch_toScan.erase(i++);
833 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
837 m_ch_scanned.clear();
838 m_ch_unavailable.clear();
839 m_new_channels.clear();
840 m_new_services.clear();
841 m_last_service = m_new_services.end();
843 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
846 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
848 if (sameChannel(*i, *ii, true))
855 m_ch_toScan.push_back(*i);
861 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
863 if (m_flags & scanRemoveServices)
865 bool clearTerrestrial=false;
866 bool clearCable=false;
867 std::set<unsigned int> scanned_sat_positions;
869 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
870 for (;it != m_ch_scanned.end(); ++it)
872 if (m_flags & scanDontRemoveUnscanned)
873 db->removeServices(&(*(*it)));
877 (*it)->getSystem(system);
880 case iDVBFrontend::feSatellite:
882 eDVBFrontendParametersSatellite sat_parm;
883 (*it)->getDVBS(sat_parm);
884 scanned_sat_positions.insert(sat_parm.orbital_position);
887 case iDVBFrontend::feTerrestrial:
889 clearTerrestrial=true;
892 case iDVBFrontend::feCable:
901 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
903 if (m_flags & scanDontRemoveUnscanned)
904 db->removeServices(&(*(*it)));
908 (*it)->getSystem(system);
911 case iDVBFrontend::feSatellite:
913 eDVBFrontendParametersSatellite sat_parm;
914 (*it)->getDVBS(sat_parm);
915 scanned_sat_positions.insert(sat_parm.orbital_position);
918 case iDVBFrontend::feTerrestrial:
920 clearTerrestrial=true;
923 case iDVBFrontend::feCable:
932 if (clearTerrestrial)
935 chid.dvbnamespace=0xEEEE0000;
936 db->removeServices(chid);
941 chid.dvbnamespace=0xFFFF0000;
942 db->removeServices(chid);
944 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
947 if (m_flags & scanDontRemoveFeeds)
948 chid.dvbnamespace = eDVBNamespace((*x)<<16);
949 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
950 db->removeServices(chid, *x);
954 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
955 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
958 ch->second->getSystem(system);
959 if (system == iDVBFrontend::feTerrestrial)
961 std::map<eDVBChannelID, unsigned int>::iterator it = m_corrected_frequencys.find(ch->first);
962 if (it != m_corrected_frequencys.end())
964 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
965 eDVBFrontendParametersTerrestrial parm;
967 eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
968 ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
969 ch->first.dvbnamespace.get(), it->second, parm.frequency);
970 parm.frequency = it->second;
972 m_corrected_frequencys.erase(it);
975 if (m_flags & scanOnlyFree)
977 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
978 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
980 db->addChannelToList(ch->first, ch->second);
983 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
984 service(m_new_services.begin()); service != m_new_services.end(); ++service)
986 ePtr<eDVBService> dvb_service;
987 if (!db->getService(service->first, dvb_service))
989 if (dvb_service->m_flags & eDVBService::dxNoSDT)
991 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
993 dvb_service->m_service_name = service->second->m_service_name;
994 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
996 dvb_service->m_provider_name = service->second->m_provider_name;
997 if (service->second->m_ca.size())
998 dvb_service->m_ca = service->second->m_ca;
999 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
1000 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1004 db->addService(service->first, service->second);
1005 if (!(m_flags & scanRemoveServices))
1006 service->second->m_flags |= eDVBService::dxNewFound;
1011 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1013 const ServiceDescriptionList &services = *sdt.getDescriptions();
1014 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1015 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1017 /* save correct CHID for this channel */
1018 m_chid_current = chid;
1020 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1022 unsigned short service_id = (*s)->getServiceId();
1023 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1026 if (m_flags & scanOnlyFree)
1028 std::map<unsigned short, service>::iterator it =
1029 m_pmts_to_read.find(service_id);
1030 if (it != m_pmts_to_read.end())
1032 if (it->second.scrambled)
1034 SCAN_eDebug("is scrambled!");
1038 SCAN_eDebug("is free");
1041 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1048 eServiceReferenceDVB ref;
1049 ePtr<eDVBService> service = new eDVBService;
1052 ref.setServiceID(service_id);
1054 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1055 desc != (*s)->getDescriptors()->end(); ++desc)
1057 switch ((*desc)->getTag())
1059 case SERVICE_DESCRIPTOR:
1061 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1062 ref.setServiceType(d.getServiceType());
1063 service->m_service_name = convertDVBUTF8(d.getServiceName());
1064 service->genSortName();
1066 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1067 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1070 case CA_IDENTIFIER_DESCRIPTOR:
1072 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1073 const CaSystemIdList &caids = *d.getCaSystemIds();
1074 SCAN_eDebugNoNewLine("CA ");
1075 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1077 SCAN_eDebugNoNewLine("%04x ", *i);
1078 service->m_ca.push_front(*i);
1084 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1089 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1090 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1094 m_last_service = i.first;
1095 m_event(evtNewService);
1098 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1099 m_abort_current_pmt = true;
1101 m_pmts_to_read.erase(service_id);
1107 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1109 connection = new eConnection(this, m_event.connect(event));
1113 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1115 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1116 transponders_total = m_ch_toScan.size() + transponders_done;
1117 services = m_new_services.size();
1120 void eDVBScan::getLastServiceName(std::string &last_service_name)
1122 if (m_last_service == m_new_services.end())
1123 last_service_name = "";
1125 last_service_name = m_last_service->second->m_service_name;
1128 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1131 return m_channel->getFrontend(fe);
1136 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)