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/eenv.h>
14 #include <lib/base/eerror.h>
15 #include <lib/base/estring.h>
16 #include <lib/python/python.h>
19 #define SCAN_eDebug(x...) do { if (m_scan_debug) eDebug(x); } while(0)
20 #define SCAN_eDebugNoNewLine(x...) do { if (m_scan_debug) eDebugNoNewLine(x); } while(0)
24 eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug)
25 :m_channel(channel), m_channel_state(iDVBChannel::state_idle)
26 ,m_ready(0), m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT)
27 ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0)
28 ,m_usePAT(usePAT), m_scan_debug(debug), m_show_add_tsid_onid_check_failed_msg(true)
30 if (m_channel->getDemux(m_demux))
31 SCAN_eDebug("scan: failed to allocate demux!");
32 m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
33 std::string filename = eEnv::resolve("${sysconfdir}/scan_tp_valid_check.py");
34 FILE *f = fopen(filename.c_str(), "r");
38 size_t rd = fread(code, 1, 16383, f);
42 m_additional_tsid_onid_check_func = Py_CompileString(code, filename.c_str(), Py_file_input);
50 if (m_additional_tsid_onid_check_func)
51 Py_DECREF(m_additional_tsid_onid_check_func);
54 int eDVBScan::isValidONIDTSID(int orbital_position, eOriginalNetworkID onid, eTransportStreamID tsid)
63 case 0x13E: // workaround for 11258H and 11470V on hotbird with same ONID/TSID (0x13E/0x578)
64 ret = orbital_position != 130 || tsid != 0x578;
67 ret = orbital_position == 192;
76 ret = abs(orbital_position-282) < 6 && tsid != 2019;
77 // 12070H and 10936V have same tsid/onid.. but even the same services are provided
82 case 0x5E: // Sirius 4.8E 12322V and 12226H
83 ret = abs(orbital_position-48) < 3 && tsid != 1;
85 case 10100: // Eutelsat W7 36.0E 11644V and 11652V
86 ret = orbital_position != 360 || tsid != 10187;
88 case 42: // Tuerksat 42.0E
89 ret = orbital_position != 420 || (
90 tsid != 8 && // 11830V 12729V
91 tsid != 5 && // 12679V 12685H
92 tsid != 2 && // 11096V 12015H
93 tsid != 55); // 11996V 11716V
95 case 100: // Intelsat 10 68.5E 3808V 3796V 4012V, Amos 4.0W 10723V 11571H
96 ret = (orbital_position != 685 && orbital_position != 3560) || tsid != 1;
98 case 70: // Thor 0.8W 11862H 12341V
99 ret = abs(orbital_position-3592) < 3 && tsid != 46;
101 case 32: // NSS 806 (40.5W) 4059R, 3774L
102 ret = orbital_position != 3195 || tsid != 21;
105 ret = onid.get() < 0xFF00;
108 if (ret && m_additional_tsid_onid_check_func)
111 ePyObject dict = PyDict_New();
112 extern void PutToDict(ePyObject &, const char *, long);
113 PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
114 PutToDict(dict, "orbpos", orbital_position);
115 PutToDict(dict, "tsid", tsid.get());
116 PutToDict(dict, "onid", onid.get());
117 ePyObject r = PyEval_EvalCode((PyCodeObject*)(PyObject*)m_additional_tsid_onid_check_func, dict, dict);
120 ePyObject o = PyDict_GetItemString(dict, "ret");
125 ret = PyInt_AsLong(o);
131 if (failed && m_show_add_tsid_onid_check_failed_msg)
133 eDebug("execing /etc/enigma2/scan_tp_valid_check failed!\n"
134 "usable global variables in scan_tp_valid_check.py are 'orbpos', 'tsid', 'onid'\n"
135 "the return value must be stored in a global var named 'ret'");
136 m_show_add_tsid_onid_check_failed_msg=false;
143 eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash)
145 // on valid ONIDs, ignore frequency ("sub network") part
146 if (isValidONIDTSID((hash >> 16) & 0xFFFF, onid, tsid))
148 return eDVBNamespace(hash);
151 void eDVBScan::stateChange(iDVBChannel *ch)
154 if (ch->getState(state))
156 if (m_channel_state == state)
159 if (state == iDVBChannel::state_ok)
162 m_channel_state = state;
163 } else if (state == iDVBChannel::state_failed)
165 m_ch_unavailable.push_back(m_ch_current);
168 /* unavailable will timeout, anyway. */
171 RESULT eDVBScan::nextChannel()
173 ePtr<iDVBFrontend> fe;
175 m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0;
179 m_pat_tsid = eTransportStreamID();
181 /* check what we need */
182 m_ready_all = readySDT;
184 if (m_flags & scanNetworkSearch)
185 m_ready_all |= readyNIT;
187 if (m_flags & scanSearchBAT)
188 m_ready_all |= readyBAT;
191 m_ready_all |= readyPAT;
193 if (m_ch_toScan.empty())
195 SCAN_eDebug("no channels left to scan.");
196 SCAN_eDebug("%zd channels scanned, %zd were unavailable.",
197 m_ch_scanned.size(), m_ch_unavailable.size());
198 SCAN_eDebug("%zd channels in database.", m_new_channels.size());
203 m_ch_current = m_ch_toScan.front();
205 m_ch_toScan.pop_front();
207 if (m_channel->getFrontend(fe))
213 m_chid_current = eDVBChannelID();
215 m_channel_state = iDVBChannel::state_idle;
217 if (fe->tune(*m_ch_current))
218 return nextChannel();
224 RESULT eDVBScan::startFilter()
229 /* only start required filters filter */
231 if (m_ready_all & readyPAT)
232 startSDT = m_ready & readyPAT;
234 // m_ch_current is not set, when eDVBScan is just used for a SDT update
237 unsigned int channelFlags;
238 m_channel->getCurrentFrontendParameters(m_ch_current);
239 m_ch_current->getFlags(channelFlags);
240 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
241 m_flags |= scanOnlyFree;
245 if (startSDT && (m_ready_all & readySDT))
247 m_SDT = new eTable<ServiceDescriptionSection>(m_scan_debug);
249 if (m_ready & readyPAT && m_ready & validPAT)
251 std::vector<ProgramAssociationSection*>::const_iterator i =
252 m_PAT->getSections().begin();
253 ASSERT(i != m_PAT->getSections().end());
254 tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
255 m_pat_tsid = eTransportStreamID(tsid);
256 for (; i != m_PAT->getSections().end(); ++i)
258 const ProgramAssociationSection &pat = **i;
259 ProgramAssociationConstIterator program = pat.getPrograms()->begin();
260 for (; program != pat.getPrograms()->end(); ++program)
261 m_pmts_to_read.insert(std::pair<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
263 m_PMT = new eTable<ProgramMapSection>(m_scan_debug);
264 CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
266 // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
270 m_ch_current->getSystem(type);
271 if (type == iDVBFrontend::feCable)
273 eDVBFrontendParametersCable parm;
274 m_ch_current->getDVBC(parm);
275 if ((tsid == 0x00d7 && abs(parm.frequency-618000) < 2000) ||
276 (tsid == 0x00d8 && abs(parm.frequency-626000) < 2000))
283 if (m_SDT->start(m_demux, eDVBSDTSpec()))
286 else if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
288 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
291 if (!(m_ready & readyPAT))
294 if (m_ready_all & readyPAT)
296 m_PAT = new eTable<ProgramAssociationSection>(m_scan_debug);
297 if (m_PAT->start(m_demux, eDVBPATSpec(4000)))
299 CONNECT(m_PAT->tableReady, eDVBScan::PATready);
303 if (m_ready_all & readyNIT)
305 m_NIT = new eTable<NetworkInformationSection>(m_scan_debug);
306 if (m_NIT->start(m_demux, eDVBNITSpec()))
308 CONNECT(m_NIT->tableReady, eDVBScan::NITready);
312 if (m_ready_all & readyBAT)
314 m_BAT = new eTable<BouquetAssociationSection>(m_scan_debug);
315 if (m_BAT->start(m_demux, eDVBBATSpec()))
317 CONNECT(m_BAT->tableReady, eDVBScan::BATready);
323 void eDVBScan::SDTready(int err)
325 SCAN_eDebug("got sdt %d", err);
332 void eDVBScan::NITready(int err)
334 SCAN_eDebug("got nit, err %d", err);
341 void eDVBScan::BATready(int err)
343 SCAN_eDebug("got bat");
350 void eDVBScan::PATready(int err)
352 SCAN_eDebug("got pat");
356 startFilter(); // for starting the SDT filter
359 void eDVBScan::PMTready(int err)
361 SCAN_eDebug("got pmt %d", err);
364 bool scrambled = false;
365 bool have_audio = false;
366 bool have_video = false;
367 unsigned short pcrpid = 0xFFFF;
368 std::vector<ProgramMapSection*>::const_iterator i;
370 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
372 const ProgramMapSection &pmt = **i;
373 if (pcrpid == 0xFFFF)
374 pcrpid = pmt.getPcrPid();
376 SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
377 ElementaryStreamInfoConstIterator es;
378 for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
380 int isaudio = 0, isvideo = 0, is_scrambled = 0, forced_audio = 0, forced_video = 0;
381 switch ((*es)->getType())
383 case 0x1b: // AVC Video Stream (MPEG4 H264)
384 case 0x24: // H265 HEVC
385 case 0x10: // MPEG 4 Part 2
386 case 0x01: // MPEG 1 video
387 case 0x02: // MPEG 2 video
390 //break; fall through !!!
391 case 0x03: // MPEG 1 audio
392 case 0x04: // MPEG 2 audio
393 case 0x0f: // MPEG 2 AAC
394 case 0x11: // MPEG 4 AAC
400 case 0x06: // PES Private
401 case 0x81: // user private
402 case 0xEA: // TS_PSI_ST_SMPTE_VC1
403 for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
404 desc != (*es)->getDescriptors()->end(); ++desc)
406 uint8_t tag = (*desc)->getTag();
407 /* PES private can contain AC-3, DTS or lots of other stuff.
408 check descriptors to get the exakt type. */
409 if (!forced_video && !forced_audio)
413 case 0x1C: // TS_PSI_DT_MPEG4_Audio
414 case 0x2B: // TS_PSI_DT_MPEG2_AAC
418 case AUDIO_STREAM_DESCRIPTOR:
421 case 0x28: // TS_PSI_DT_AVC
422 case 0x1B: // TS_PSI_DT_MPEG4_Video
423 case VIDEO_STREAM_DESCRIPTOR:
426 case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
428 RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc);
429 switch (d->getFormatIdentifier())
431 case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
432 case 0x41432d33: // == 'AC-3'
433 case 0x42535344: // == 'BSSD' (LPCM)
436 case 0x56432d31: // == 'VC-1'
447 if (tag == CA_DESCRIPTOR)
462 for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
463 desc != pmt.getDescriptors()->end(); ++desc)
465 if ((*desc)->getTag() == CA_DESCRIPTOR)
469 m_pmt_in_progress->second.scrambled = scrambled;
471 m_pmt_in_progress->second.serviceType = 1;
472 else if ( have_audio )
473 m_pmt_in_progress->second.serviceType = 2;
475 m_pmt_in_progress->second.serviceType = 100;
477 if (err == -1) // timeout or removed by sdt
478 m_pmts_to_read.erase(m_pmt_in_progress++);
479 else if (m_pmt_running)
483 m_pmt_in_progress = m_pmts_to_read.begin();
484 m_pmt_running = true;
487 if (m_pmt_in_progress != m_pmts_to_read.end())
488 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
492 m_pmt_running = false;
498 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
500 /* add it to the list of known channels. */
502 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
505 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
507 /* check if we don't already have that channel ... */
510 feparm->getSystem(type);
514 case iDVBFrontend::feSatellite:
516 eDVBFrontendParametersSatellite parm;
517 feparm->getDVBS(parm);
518 SCAN_eDebug("try to add %d %d %d %d %d %d",
519 parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
522 case iDVBFrontend::feCable:
524 eDVBFrontendParametersCable parm;
525 feparm->getDVBC(parm);
526 SCAN_eDebug("try to add %d %d %d %d",
527 parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
530 case iDVBFrontend::feTerrestrial:
532 eDVBFrontendParametersTerrestrial parm;
533 feparm->getDVBT(parm);
534 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
535 parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
536 parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
542 /* ... in the list of channels to scan */
543 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
545 if (sameChannel(*i, feparm))
549 *i = feparm; // update
550 SCAN_eDebug("update");
554 SCAN_eDebug("remove dupe");
555 m_ch_toScan.erase(i++);
565 SCAN_eDebug("already in todo list");
569 /* ... in the list of successfully scanned channels */
570 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
571 if (sameChannel(*i, feparm))
573 SCAN_eDebug("successfully scanned");
577 /* ... in the list of unavailable channels */
578 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
579 if (sameChannel(*i, feparm, true))
581 SCAN_eDebug("scanned but not available");
585 /* ... on the current channel */
586 if (sameChannel(m_ch_current, feparm))
588 SCAN_eDebug("is current");
592 SCAN_eDebug("really add");
593 /* otherwise, add it to the todo list. */
594 m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
597 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
600 if (ch1->calculateDifference(ch2, diff, exact))
602 if (diff < 4000) // more than 4mhz difference?
607 void eDVBScan::channelDone()
609 if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
611 unsigned long hash = 0;
613 m_ch_current->getHash(hash);
615 eDVBNamespace dvbnamespace = buildNamespace(
616 (**m_SDT->getSections().begin()).getOriginalNetworkId(),
617 (**m_SDT->getSections().begin()).getTransportStreamId(),
620 SCAN_eDebug("SDT: ");
621 std::vector<ServiceDescriptionSection*>::const_iterator i;
622 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
623 processSDT(dvbnamespace, **i);
624 m_ready &= ~validSDT;
627 if (m_ready & validNIT)
630 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
631 m_ch_current->getSystem(system);
632 SCAN_eDebug("dumping NIT");
633 if (m_flags & clearToScanOnFirstNIT)
635 m_ch_toScan_backup = m_ch_toScan;
638 std::vector<NetworkInformationSection*>::const_iterator i;
639 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
641 const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
643 for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin());
644 tsinfo != tsinfovec.end(); ++tsinfo)
646 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
647 (*tsinfo)->getOriginalNetworkId());
649 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
650 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
652 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
653 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
655 switch ((*desc)->getTag())
657 case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
659 if (system != iDVBFrontend::feCable)
660 break; // when current locked transponder is no cable transponder ignore this descriptor
661 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
662 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
663 eDVBFrontendParametersCable cable;
665 feparm->setDVBC(cable);
667 unsigned long hash=0;
668 feparm->getHash(hash);
669 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
672 eDVBChannelID(ns, tsid, onid),
676 case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
678 if (system != iDVBFrontend::feTerrestrial)
679 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
680 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
681 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
682 eDVBFrontendParametersTerrestrial terr;
684 feparm->setDVBT(terr);
686 unsigned long hash=0;
687 feparm->getHash(hash);
688 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
691 eDVBChannelID(ns, tsid, onid),
695 case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
697 if (system != iDVBFrontend::feSatellite)
698 break; // when current locked transponder is no satellite transponder ignore this descriptor
700 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
701 if (d.getFrequency() < 10000)
704 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
705 eDVBFrontendParametersSatellite sat;
708 eDVBFrontendParametersSatellite p;
709 m_ch_current->getDVBS(p);
711 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
712 sat.orbital_position = p.orbital_position;
714 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
716 SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
717 sat.orbital_position = p.orbital_position;
720 feparm->setDVBS(sat);
722 if ( p.orbital_position != sat.orbital_position)
723 SCAN_eDebug("dropping this transponder, it's on another satellite.");
726 unsigned long hash=0;
727 feparm->getHash(hash);
729 eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
735 SCAN_eDebug("descr<%x>", (*desc)->getTag());
743 /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
744 no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
747 This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
749 if (m_flags & clearToScanOnFirstNIT)
751 if (m_ch_toScan.empty())
753 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
754 m_ch_toScan = m_ch_toScan_backup;
756 m_flags &= ~clearToScanOnFirstNIT;
758 m_ready &= ~validNIT;
761 if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
763 if (m_abort_current_pmt)
765 m_abort_current_pmt = false;
771 SCAN_eDebug("channel done!");
773 /* if we had services on this channel, we declare
774 this channels as "known good". add it.
776 (TODO: not yet implemented)
777 a NIT entry could have possible overridden
778 our frontend data with more exact data.
780 (TODO: not yet implemented)
781 the tuning process could have lead to more
782 exact data than the user entered.
784 The channel id was probably corrected
785 by the data written in the SDT. this is
786 important, as "initial transponder lists"
787 usually don't have valid CHIDs (and that's
790 These are the reasons for adding the transponder
791 here, and not before.
795 if (m_ch_current->getSystem(type))
798 for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
800 eServiceReferenceDVB ref;
801 ePtr<eDVBService> service = new eDVBService;
805 unsigned long hash = 0;
807 m_ch_current->getHash(hash);
809 m_chid_current = eDVBChannelID(
810 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
811 m_pat_tsid, eOriginalNetworkID(0));
814 if (m_pmt_in_progress->second.serviceType == 1)
815 SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
816 else if (m_pmt_in_progress->second.serviceType == 2)
817 SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
819 SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
821 ref.set(m_chid_current);
822 ref.setServiceID(m_pmt_in_progress->first);
823 ref.setServiceType(m_pmt_in_progress->second.serviceType);
829 memset(pname, 0, sizeof(pname));
830 memset(sname, 0, sizeof(sname));
833 case iDVBFrontend::feSatellite:
835 eDVBFrontendParametersSatellite parm;
836 m_ch_current->getDVBS(parm);
837 snprintf(sname, 255, "%d%c SID 0x%02x",
839 parm.polarisation ? 'V' : 'H',
840 m_pmt_in_progress->first);
841 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
842 parm.system ? "DVB-S2" : "DVB-S",
843 parm.modulation == 1 ? "QPSK" : "8PSK",
845 parm.polarisation ? 'V' : 'H',
846 parm.orbital_position/10,
847 parm.orbital_position%10,
848 parm.orbital_position > 0 ? 'E' : 'W');
851 case iDVBFrontend::feTerrestrial:
853 eDVBFrontendParametersTerrestrial parm;
854 m_ch_current->getDVBT(parm);
855 snprintf(sname, 255, "%d SID 0x%02x",
857 m_pmt_in_progress->first);
860 case iDVBFrontend::feCable:
862 eDVBFrontendParametersCable parm;
863 m_ch_current->getDVBC(parm);
864 snprintf(sname, 255, "%d SID 0x%02x",
866 m_pmt_in_progress->first);
870 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
871 service->m_service_name = convertDVBUTF8(sname);
872 service->genSortName();
873 service->m_provider_name = convertDVBUTF8(pname);
876 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
877 SCAN_eDebug("add not scrambled!");
878 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
879 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
882 m_last_service = i.first;
883 m_event(evtNewService);
887 SCAN_eDebug("dont add... is scrambled!");
888 m_pmts_to_read.erase(m_pmt_in_progress++);
892 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
895 addKnownGoodChannel(m_chid_current, m_ch_current);
900 case iDVBFrontend::feSatellite:
901 case iDVBFrontend::feTerrestrial:
902 case iDVBFrontend::feCable:
904 ePtr<iDVBFrontend> fe;
905 if (!m_channel->getFrontend(fe))
907 ePyObject tp_dict = PyDict_New();
908 fe->getTransponderData(tp_dict, false);
909 // eDebug("add tuner data for tsid %04x, onid %04x, ns %08x",
910 // m_chid_current.transport_stream_id.get(), m_chid_current.original_network_id.get(),
911 // m_chid_current.dvbnamespace.get());
912 m_tuner_data.insert(std::pair<eDVBChannelID, ePyObjectWrapper>(m_chid_current, tp_dict));
922 m_ch_scanned.push_back(m_ch_current);
924 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
926 if (sameChannel(*i, m_ch_current))
928 SCAN_eDebug("remove dupe 2");
929 m_ch_toScan.erase(i++);
938 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
942 m_ch_scanned.clear();
943 m_ch_unavailable.clear();
944 m_new_channels.clear();
945 m_tuner_data.clear();
946 m_new_services.clear();
947 m_last_service = m_new_services.end();
949 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
952 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
954 if (sameChannel(*i, *ii, true))
961 m_ch_toScan.push_back(*i);
967 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
969 if (m_flags & scanRemoveServices)
971 bool clearTerrestrial=false;
972 bool clearCable=false;
973 std::set<unsigned int> scanned_sat_positions;
975 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
976 for (;it != m_ch_scanned.end(); ++it)
978 if (m_flags & scanDontRemoveUnscanned)
979 db->removeServices(&(*(*it)));
983 (*it)->getSystem(system);
986 case iDVBFrontend::feSatellite:
988 eDVBFrontendParametersSatellite sat_parm;
989 (*it)->getDVBS(sat_parm);
990 scanned_sat_positions.insert(sat_parm.orbital_position);
993 case iDVBFrontend::feTerrestrial:
995 clearTerrestrial=true;
998 case iDVBFrontend::feCable:
1007 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
1009 if (m_flags & scanDontRemoveUnscanned)
1010 db->removeServices(&(*(*it)));
1014 (*it)->getSystem(system);
1017 case iDVBFrontend::feSatellite:
1019 eDVBFrontendParametersSatellite sat_parm;
1020 (*it)->getDVBS(sat_parm);
1021 scanned_sat_positions.insert(sat_parm.orbital_position);
1024 case iDVBFrontend::feTerrestrial:
1026 clearTerrestrial=true;
1029 case iDVBFrontend::feCable:
1038 if (clearTerrestrial)
1041 chid.dvbnamespace=0xEEEE0000;
1042 db->removeServices(chid);
1047 chid.dvbnamespace=0xFFFF0000;
1048 db->removeServices(chid);
1050 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
1053 if (m_flags & scanDontRemoveFeeds)
1054 chid.dvbnamespace = eDVBNamespace((*x)<<16);
1055 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
1056 db->removeServices(chid, *x);
1060 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
1061 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
1064 ch->second->getSystem(system);
1065 std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
1069 case iDVBFrontend::feTerrestrial:
1071 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
1072 eDVBFrontendParametersTerrestrial parm;
1073 int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
1075 // eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
1076 // ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
1077 // ch->first.dvbnamespace.get(), freq, parm.frequency);
1078 parm.frequency = freq;
1082 case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
1083 case iDVBFrontend::feCable:
1087 if (m_flags & scanOnlyFree)
1089 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
1090 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
1093 db->addChannelToList(ch->first, ch->second);
1096 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
1097 service(m_new_services.begin()); service != m_new_services.end(); ++service)
1099 ePtr<eDVBService> dvb_service;
1100 if (!db->getService(service->first, dvb_service))
1102 if (dvb_service->m_flags & eDVBService::dxNoSDT)
1104 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
1106 dvb_service->m_service_name = service->second->m_service_name;
1107 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
1109 dvb_service->m_provider_name = service->second->m_provider_name;
1110 if (service->second->m_ca.size())
1111 dvb_service->m_ca = service->second->m_ca;
1112 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
1113 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1117 db->addService(service->first, service->second);
1118 if (!(m_flags & scanRemoveServices))
1119 service->second->m_flags |= eDVBService::dxNewFound;
1124 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1126 const ServiceDescriptionList &services = *sdt.getDescriptions();
1127 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1128 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1130 /* save correct CHID for this channel */
1131 m_chid_current = chid;
1133 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1135 unsigned short service_id = (*s)->getServiceId();
1136 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1139 if (m_flags & scanOnlyFree)
1141 std::map<unsigned short, service>::iterator it =
1142 m_pmts_to_read.find(service_id);
1143 if (it != m_pmts_to_read.end())
1145 if (it->second.scrambled)
1147 SCAN_eDebug("is scrambled!");
1151 SCAN_eDebug("is free");
1154 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1161 eServiceReferenceDVB ref;
1162 ePtr<eDVBService> service = new eDVBService;
1165 ref.setServiceID(service_id);
1167 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1168 desc != (*s)->getDescriptors()->end(); ++desc)
1170 switch ((*desc)->getTag())
1172 case SERVICE_DESCRIPTOR:
1174 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1175 ref.setServiceType(d.getServiceType());
1176 service->m_service_name = convertDVBUTF8(d.getServiceName());
1177 service->genSortName();
1179 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1180 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1183 case CA_IDENTIFIER_DESCRIPTOR:
1185 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1186 const CaSystemIdList &caids = *d.getCaSystemIds();
1187 SCAN_eDebugNoNewLine("CA ");
1188 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1190 SCAN_eDebugNoNewLine("%04x ", *i);
1191 service->m_ca.push_front(*i);
1197 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1202 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1203 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1207 m_last_service = i.first;
1208 m_event(evtNewService);
1211 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1212 m_abort_current_pmt = true;
1214 m_pmts_to_read.erase(service_id);
1220 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1222 connection = new eConnection(this, m_event.connect(event));
1226 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1228 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1229 transponders_total = m_ch_toScan.size() + transponders_done;
1230 services = m_new_services.size();
1233 void eDVBScan::getLastServiceName(std::string &last_service_name)
1235 if (m_last_service == m_new_services.end())
1236 last_service_name = "";
1238 last_service_name = m_last_service->second->m_service_name;
1241 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1244 return m_channel->getFrontend(fe);
1249 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)