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++/t2_delivery_system_descriptor.h>
7 #include <dvbsi++/cable_delivery_system_descriptor.h>
8 #include <dvbsi++/ca_identifier_descriptor.h>
9 #include <dvbsi++/registration_descriptor.h>
10 #include <dvbsi++/extension_descriptor.h>
11 #include <dvbsi++/frequency_list_descriptor.h>
12 #include <lib/dvb/specs.h>
13 #include <lib/dvb/esection.h>
14 #include <lib/dvb/scan.h>
15 #include <lib/dvb/frontend.h>
16 #include <lib/base/eenv.h>
17 #include <lib/base/eerror.h>
18 #include <lib/base/estring.h>
19 #include <lib/python/python.h>
22 #define SCAN_eDebug(x...) do { if (m_scan_debug) eDebug(x); } while(0)
23 #define SCAN_eDebugNoNewLine(x...) do { if (m_scan_debug) eDebugNoNewLine(x); } while(0)
27 eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug)
28 :m_channel(channel), m_channel_state(iDVBChannel::state_idle)
29 ,m_ready(0), m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT)
30 ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0)
31 ,m_usePAT(usePAT), m_scan_debug(debug), m_show_add_tsid_onid_check_failed_msg(true)
33 if (m_channel->getDemux(m_demux))
34 SCAN_eDebug("scan: failed to allocate demux!");
35 m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
36 std::string filename = eEnv::resolve("${sysconfdir}/scan_tp_valid_check.py");
37 FILE *f = fopen(filename.c_str(), "r");
41 size_t rd = fread(code, 1, 16383, f);
45 m_additional_tsid_onid_check_func = Py_CompileString(code, filename.c_str(), Py_file_input);
53 if (m_additional_tsid_onid_check_func)
54 Py_DECREF(m_additional_tsid_onid_check_func);
57 int eDVBScan::isValidONIDTSID(int orbital_position, eOriginalNetworkID onid, eTransportStreamID tsid)
66 case 0x13E: // workaround for 11258H and 11470V on hotbird with same ONID/TSID (0x13E/0x578)
67 ret = orbital_position != 130 || tsid != 0x578;
70 ret = orbital_position == 192;
79 ret = abs(orbital_position-282) < 6 && tsid != 2019;
80 // 12070H and 10936V have same tsid/onid.. but even the same services are provided
85 case 0x5E: // Sirius 4.8E 12322V and 12226H
86 ret = abs(orbital_position-48) < 3 && tsid != 1;
88 case 10100: // Eutelsat W7 36.0E 11644V and 11652V
89 ret = orbital_position != 360 || tsid != 10187;
91 case 42: // Tuerksat 42.0E
92 ret = orbital_position != 420 || (
93 tsid != 8 && // 11830V 12729V
94 tsid != 5 && // 12679V 12685H
95 tsid != 2 && // 11096V 12015H
96 tsid != 55); // 11996V 11716V
98 case 100: // Intelsat 10 68.5E 3808V 3796V 4012V, Amos 4.0W 10723V 11571H
99 ret = (orbital_position != 685 && orbital_position != 3560) || tsid != 1;
101 case 70: // Thor 0.8W 11862H 12341V
102 ret = abs(orbital_position-3592) < 3 && tsid != 46;
104 case 32: // NSS 806 (40.5W) 4059R, 3774L
105 ret = orbital_position != 3195 || tsid != 21;
108 ret = onid.get() < 0xFF00;
111 if (ret && m_additional_tsid_onid_check_func)
114 ePyObject dict = PyDict_New();
115 extern void PutToDict(ePyObject &, const char *, long);
116 PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
117 PutToDict(dict, "orbpos", orbital_position);
118 PutToDict(dict, "tsid", tsid.get());
119 PutToDict(dict, "onid", onid.get());
120 ePyObject r = PyEval_EvalCode((PyCodeObject*)(PyObject*)m_additional_tsid_onid_check_func, dict, dict);
123 ePyObject o = PyDict_GetItemString(dict, "ret");
128 ret = PyInt_AsLong(o);
134 if (failed && m_show_add_tsid_onid_check_failed_msg)
136 eDebug("execing /etc/enigma2/scan_tp_valid_check failed!\n"
137 "usable global variables in scan_tp_valid_check.py are 'orbpos', 'tsid', 'onid'\n"
138 "the return value must be stored in a global var named 'ret'");
139 m_show_add_tsid_onid_check_failed_msg=false;
146 eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash)
148 // on valid ONIDs, ignore frequency ("sub network") part
149 if (isValidONIDTSID((hash >> 16) & 0xFFFF, onid, tsid))
151 return eDVBNamespace(hash);
154 void eDVBScan::stateChange(iDVBChannel *ch)
157 if (ch->getState(state))
159 if (m_channel_state == state)
162 if (state == iDVBChannel::state_ok)
165 m_channel_state = state;
166 } else if (state == iDVBChannel::state_failed)
168 m_ch_unavailable.push_back(m_ch_current);
171 /* unavailable will timeout, anyway. */
174 RESULT eDVBScan::nextChannel()
176 ePtr<iDVBFrontend> fe;
178 m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0;
182 m_pat_tsid = eTransportStreamID();
184 /* check what we need */
185 m_ready_all = readySDT;
187 if (m_flags & scanNetworkSearch)
188 m_ready_all |= readyNIT;
190 if (m_flags & scanSearchBAT)
191 m_ready_all |= readyBAT;
194 m_ready_all |= readyPAT;
196 if (m_ch_toScan.empty())
198 SCAN_eDebug("no channels left to scan.");
199 SCAN_eDebug("%zd channels scanned, %zd were unavailable.",
200 m_ch_scanned.size(), m_ch_unavailable.size());
201 SCAN_eDebug("%zd channels in database.", m_new_channels.size());
206 m_ch_current = m_ch_toScan.front();
208 m_ch_toScan.pop_front();
210 if (m_channel->getFrontend(fe))
216 m_chid_current = eDVBChannelID();
218 m_channel_state = iDVBChannel::state_idle;
220 if (fe->tune(*m_ch_current))
221 return nextChannel();
227 RESULT eDVBScan::startFilter()
232 /* only start required filters filter */
234 if (m_ready_all & readyPAT)
235 startSDT = m_ready & readyPAT;
237 // m_ch_current is not set, when eDVBScan is just used for a SDT update
240 unsigned int channelFlags;
241 m_channel->getCurrentFrontendParameters(m_ch_current);
242 m_ch_current->getFlags(channelFlags);
243 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
244 m_flags |= scanOnlyFree;
248 if (startSDT && (m_ready_all & readySDT))
250 m_SDT = new eTable<ServiceDescriptionSection>(m_scan_debug);
252 if (m_ready & readyPAT && m_ready & validPAT)
254 std::vector<ProgramAssociationSection*>::const_iterator i =
255 m_PAT->getSections().begin();
256 ASSERT(i != m_PAT->getSections().end());
257 tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
258 m_pat_tsid = eTransportStreamID(tsid);
259 for (; i != m_PAT->getSections().end(); ++i)
261 const ProgramAssociationSection &pat = **i;
262 ProgramAssociationConstIterator program = pat.getPrograms()->begin();
263 for (; program != pat.getPrograms()->end(); ++program)
264 m_pmts_to_read.insert(std::pair<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
266 m_PMT = new eTable<ProgramMapSection>(m_scan_debug);
267 CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
269 // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
273 m_ch_current->getSystem(type);
274 if (type == iDVBFrontend::feCable)
276 eDVBFrontendParametersCable parm;
277 m_ch_current->getDVBC(parm);
278 if ((tsid == 0x00d7 && abs(parm.frequency-618000) < 2000) ||
279 (tsid == 0x00d8 && abs(parm.frequency-626000) < 2000))
286 if (m_SDT->start(m_demux, eDVBSDTSpec()))
289 else if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
291 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
294 if (!(m_ready & readyPAT))
297 if (m_ready_all & readyPAT)
299 m_PAT = new eTable<ProgramAssociationSection>(m_scan_debug);
300 if (m_PAT->start(m_demux, eDVBPATSpec(4000)))
302 CONNECT(m_PAT->tableReady, eDVBScan::PATready);
306 if (m_ready_all & readyNIT)
308 m_NIT = new eTable<NetworkInformationSection>(m_scan_debug);
309 if (m_NIT->start(m_demux, eDVBNITSpec()))
311 CONNECT(m_NIT->tableReady, eDVBScan::NITready);
315 if (m_ready_all & readyBAT)
317 m_BAT = new eTable<BouquetAssociationSection>(m_scan_debug);
318 if (m_BAT->start(m_demux, eDVBBATSpec()))
320 CONNECT(m_BAT->tableReady, eDVBScan::BATready);
326 void eDVBScan::SDTready(int err)
328 SCAN_eDebug("got sdt %d", err);
335 void eDVBScan::NITready(int err)
337 SCAN_eDebug("got nit, err %d", err);
344 void eDVBScan::BATready(int err)
346 SCAN_eDebug("got bat");
353 void eDVBScan::PATready(int err)
355 SCAN_eDebug("got pat");
359 startFilter(); // for starting the SDT filter
362 void eDVBScan::PMTready(int err)
364 SCAN_eDebug("got pmt %d", err);
367 bool scrambled = false;
368 bool have_audio = false;
369 bool have_video = false;
370 unsigned short pcrpid = 0xFFFF;
371 std::vector<ProgramMapSection*>::const_iterator i;
373 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
375 const ProgramMapSection &pmt = **i;
376 if (pcrpid == 0xFFFF)
377 pcrpid = pmt.getPcrPid();
379 SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
380 ElementaryStreamInfoConstIterator es;
381 for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
383 int isaudio = 0, isvideo = 0, is_scrambled = 0, forced_audio = 0, forced_video = 0;
384 switch ((*es)->getType())
386 case 0x1b: // AVC Video Stream (MPEG4 H264)
387 case 0x24: // H265 HEVC
388 case 0x10: // MPEG 4 Part 2
389 case 0x01: // MPEG 1 video
390 case 0x02: // MPEG 2 video
393 //break; fall through !!!
394 case 0x03: // MPEG 1 audio
395 case 0x04: // MPEG 2 audio
396 case 0x0f: // MPEG 2 AAC
397 case 0x11: // MPEG 4 AAC
403 case 0x06: // PES Private
404 case 0x81: // user private
405 case 0xEA: // TS_PSI_ST_SMPTE_VC1
406 for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
407 desc != (*es)->getDescriptors()->end(); ++desc)
409 uint8_t tag = (*desc)->getTag();
410 /* PES private can contain AC-3, DTS or lots of other stuff.
411 check descriptors to get the exakt type. */
412 if (!forced_video && !forced_audio)
416 case 0x1C: // TS_PSI_DT_MPEG4_Audio
417 case 0x2B: // TS_PSI_DT_MPEG2_AAC
421 case AUDIO_STREAM_DESCRIPTOR:
424 case 0x28: // TS_PSI_DT_AVC
425 case 0x1B: // TS_PSI_DT_MPEG4_Video
426 case VIDEO_STREAM_DESCRIPTOR:
429 case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
431 RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc);
432 switch (d->getFormatIdentifier())
434 case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
435 case 0x41432d33: // == 'AC-3'
436 case 0x42535344: // == 'BSSD' (LPCM)
439 case 0x56432d31: // == 'VC-1'
450 if (tag == CA_DESCRIPTOR)
465 for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
466 desc != pmt.getDescriptors()->end(); ++desc)
468 if ((*desc)->getTag() == CA_DESCRIPTOR)
472 m_pmt_in_progress->second.scrambled = scrambled;
474 m_pmt_in_progress->second.serviceType = 1;
475 else if ( have_audio )
476 m_pmt_in_progress->second.serviceType = 2;
478 m_pmt_in_progress->second.serviceType = 100;
480 if (err == -1) // timeout or removed by sdt
481 m_pmts_to_read.erase(m_pmt_in_progress++);
482 else if (m_pmt_running)
486 m_pmt_in_progress = m_pmts_to_read.begin();
487 m_pmt_running = true;
490 if (m_pmt_in_progress != m_pmts_to_read.end())
491 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
495 m_pmt_running = false;
501 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
503 /* add it to the list of known channels. */
505 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
508 void eDVBScan::addChannelToScan(iDVBFrontendParameters *feparm)
510 /* check if we don't already have that channel ... */
513 feparm->getSystem(type);
517 case iDVBFrontend::feSatellite:
519 eDVBFrontendParametersSatellite parm;
520 feparm->getDVBS(parm);
521 SCAN_eDebug("try to add %d %d %d %d %d %d",
522 parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
525 case iDVBFrontend::feCable:
527 eDVBFrontendParametersCable parm;
528 feparm->getDVBC(parm);
529 SCAN_eDebug("try to add %d %d %d %d",
530 parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
533 case iDVBFrontend::feTerrestrial:
535 eDVBFrontendParametersTerrestrial parm;
536 feparm->getDVBT(parm);
537 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
538 parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
539 parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
545 /* ... in the list of channels to scan */
546 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
548 if (sameChannel(*i, feparm))
552 *i = feparm; // update
553 SCAN_eDebug("update");
557 SCAN_eDebug("remove dupe");
558 m_ch_toScan.erase(i++);
568 SCAN_eDebug("already in todo list");
572 /* ... in the list of successfully scanned channels */
573 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
574 if (sameChannel(*i, feparm))
576 SCAN_eDebug("successfully scanned");
580 /* ... in the list of unavailable channels */
581 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
582 if (sameChannel(*i, feparm, true))
584 SCAN_eDebug("scanned but not available");
588 /* ... on the current channel */
589 if (sameChannel(m_ch_current, feparm))
591 SCAN_eDebug("is current");
595 SCAN_eDebug("really add");
596 /* otherwise, add it to the todo list. */
597 m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
600 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
603 if (ch1->calculateDifference(ch2, diff, exact))
605 if (diff < 4000) // more than 4mhz difference?
610 void eDVBScan::channelDone()
612 if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
614 unsigned long hash = 0;
616 m_ch_current->getHash(hash);
618 eDVBNamespace dvbnamespace = buildNamespace(
619 (**m_SDT->getSections().begin()).getOriginalNetworkId(),
620 (**m_SDT->getSections().begin()).getTransportStreamId(),
623 SCAN_eDebug("SDT: ");
624 std::vector<ServiceDescriptionSection*>::const_iterator i;
625 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
626 processSDT(dvbnamespace, **i);
627 m_ready &= ~validSDT;
630 if (m_ready & validNIT)
633 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
634 m_ch_current->getSystem(system);
635 SCAN_eDebug("dumping NIT");
636 if (m_flags & clearToScanOnFirstNIT)
638 m_ch_toScan_backup = m_ch_toScan;
641 std::vector<NetworkInformationSection*>::const_iterator i;
642 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
644 const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
646 for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin());
647 tsinfo != tsinfovec.end(); ++tsinfo)
649 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
650 (*tsinfo)->getOriginalNetworkId());
653 eDVBFrontendParametersTerrestrial t2transponder;
655 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
656 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
658 switch ((*desc)->getTag())
660 case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
662 if (system != iDVBFrontend::feCable)
663 break; // when current locked transponder is no cable transponder ignore this descriptor
664 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
665 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
666 eDVBFrontendParametersCable cable;
668 feparm->setDVBC(cable);
670 addChannelToScan(feparm);
673 case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
675 if (system != iDVBFrontend::feTerrestrial)
676 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
677 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
678 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
679 eDVBFrontendParametersTerrestrial terr;
681 feparm->setDVBT(terr);
683 addChannelToScan(feparm);
686 case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
688 if (system != iDVBFrontend::feSatellite)
689 break; // when current locked transponder is no satellite transponder ignore this descriptor
691 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
692 if (d.getFrequency() < 10000)
695 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
696 eDVBFrontendParametersSatellite sat;
699 eDVBFrontendParametersSatellite p;
700 m_ch_current->getDVBS(p);
702 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
703 sat.orbital_position = p.orbital_position;
705 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
707 SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
708 sat.orbital_position = p.orbital_position;
711 feparm->setDVBS(sat);
713 if ( p.orbital_position != sat.orbital_position)
714 SCAN_eDebug("dropping this transponder, it's on another satellite.");
717 addChannelToScan(feparm);
721 case EXTENSION_DESCRIPTOR:
723 if (system != iDVBFrontend::feTerrestrial)
724 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
726 ExtensionDescriptor &d = (ExtensionDescriptor&)**desc;
727 switch (d.getExtensionTag())
729 case T2_DELIVERY_SYSTEM_DESCRIPTOR:
731 T2DeliverySystemDescriptor &d = (T2DeliverySystemDescriptor&)**desc;
732 t2transponder.set(d);
734 for (T2CellConstIterator cell = d.getCells()->begin();
735 cell != d.getCells()->end(); ++cell)
737 for (T2FrequencyConstIterator freq = (*cell)->getCentreFrequencies()->begin();
738 freq != (*cell)->getCentreFrequencies()->end(); ++freq)
740 t2transponder.frequency = (*freq) * 10;
741 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
742 feparm->setDVBT(t2transponder);
743 addChannelToScan(feparm);
749 case FREQUENCY_LIST_DESCRIPTOR:
751 if (system != iDVBFrontend::feTerrestrial)
752 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
756 FrequencyListDescriptor &d = (FrequencyListDescriptor&)**desc;
757 if (d.getCodingType() != 0x03)
760 for (CentreFrequencyConstIterator it = d.getCentreFrequencies()->begin();
761 it != d.getCentreFrequencies()->end(); ++it)
763 t2transponder.frequency = (*it) * 10;
764 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
765 feparm->setDVBT(t2transponder);
766 addChannelToScan(feparm);
771 SCAN_eDebug("descr<%x>", (*desc)->getTag());
779 /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
780 no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
783 This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
785 if (m_flags & clearToScanOnFirstNIT)
787 if (m_ch_toScan.empty())
789 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
790 m_ch_toScan = m_ch_toScan_backup;
792 m_flags &= ~clearToScanOnFirstNIT;
794 m_ready &= ~validNIT;
797 if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
799 if (m_abort_current_pmt)
801 m_abort_current_pmt = false;
807 SCAN_eDebug("channel done!");
809 /* if we had services on this channel, we declare
810 this channels as "known good". add it.
812 (TODO: not yet implemented)
813 a NIT entry could have possible overridden
814 our frontend data with more exact data.
816 (TODO: not yet implemented)
817 the tuning process could have lead to more
818 exact data than the user entered.
820 The channel id was probably corrected
821 by the data written in the SDT. this is
822 important, as "initial transponder lists"
823 usually don't have valid CHIDs (and that's
826 These are the reasons for adding the transponder
827 here, and not before.
831 if (m_ch_current->getSystem(type))
834 for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
836 eServiceReferenceDVB ref;
837 ePtr<eDVBService> service = new eDVBService;
841 unsigned long hash = 0;
843 m_ch_current->getHash(hash);
845 m_chid_current = eDVBChannelID(
846 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
847 m_pat_tsid, eOriginalNetworkID(0));
850 if (m_pmt_in_progress->second.serviceType == 1)
851 SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
852 else if (m_pmt_in_progress->second.serviceType == 2)
853 SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
855 SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
857 ref.set(m_chid_current);
858 ref.setServiceID(m_pmt_in_progress->first);
859 ref.setServiceType(m_pmt_in_progress->second.serviceType);
865 memset(pname, 0, sizeof(pname));
866 memset(sname, 0, sizeof(sname));
869 case iDVBFrontend::feSatellite:
871 eDVBFrontendParametersSatellite parm;
872 m_ch_current->getDVBS(parm);
873 snprintf(sname, 255, "%d%c SID 0x%02x",
875 parm.polarisation ? 'V' : 'H',
876 m_pmt_in_progress->first);
877 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
878 parm.system ? "DVB-S2" : "DVB-S",
879 parm.modulation == 1 ? "QPSK" : "8PSK",
881 parm.polarisation ? 'V' : 'H',
882 parm.orbital_position/10,
883 parm.orbital_position%10,
884 parm.orbital_position > 0 ? 'E' : 'W');
887 case iDVBFrontend::feTerrestrial:
889 eDVBFrontendParametersTerrestrial parm;
890 m_ch_current->getDVBT(parm);
891 snprintf(sname, 255, "%d SID 0x%02x",
893 m_pmt_in_progress->first);
896 case iDVBFrontend::feCable:
898 eDVBFrontendParametersCable parm;
899 m_ch_current->getDVBC(parm);
900 snprintf(sname, 255, "%d SID 0x%02x",
902 m_pmt_in_progress->first);
906 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
907 service->m_service_name = convertDVBUTF8(sname);
908 service->genSortName();
909 service->m_provider_name = convertDVBUTF8(pname);
912 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
913 SCAN_eDebug("add not scrambled!");
914 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
915 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
918 m_last_service = i.first;
919 m_event(evtNewService);
923 SCAN_eDebug("dont add... is scrambled!");
924 m_pmts_to_read.erase(m_pmt_in_progress++);
928 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
931 addKnownGoodChannel(m_chid_current, m_ch_current);
936 case iDVBFrontend::feSatellite:
937 case iDVBFrontend::feTerrestrial:
938 case iDVBFrontend::feCable:
940 ePtr<iDVBFrontend> fe;
941 if (!m_channel->getFrontend(fe))
943 ePyObject tp_dict = PyDict_New();
944 fe->getTransponderData(tp_dict, false);
945 // eDebug("add tuner data for tsid %04x, onid %04x, ns %08x",
946 // m_chid_current.transport_stream_id.get(), m_chid_current.original_network_id.get(),
947 // m_chid_current.dvbnamespace.get());
948 m_tuner_data.insert(std::pair<eDVBChannelID, ePyObjectWrapper>(m_chid_current, tp_dict));
958 m_ch_scanned.push_back(m_ch_current);
960 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
962 if (sameChannel(*i, m_ch_current))
964 SCAN_eDebug("remove dupe 2");
965 m_ch_toScan.erase(i++);
974 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
978 m_ch_scanned.clear();
979 m_ch_unavailable.clear();
980 m_new_channels.clear();
981 m_tuner_data.clear();
982 m_new_services.clear();
983 m_last_service = m_new_services.end();
985 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
988 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
990 if (sameChannel(*i, *ii, true))
997 m_ch_toScan.push_back(*i);
1003 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
1005 if (m_flags & scanRemoveServices)
1007 bool clearTerrestrial=false;
1008 bool clearCable=false;
1009 std::set<unsigned int> scanned_sat_positions;
1011 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
1012 for (;it != m_ch_scanned.end(); ++it)
1014 if (m_flags & scanDontRemoveUnscanned)
1015 db->removeServices(&(*(*it)));
1019 (*it)->getSystem(system);
1022 case iDVBFrontend::feSatellite:
1024 eDVBFrontendParametersSatellite sat_parm;
1025 (*it)->getDVBS(sat_parm);
1026 scanned_sat_positions.insert(sat_parm.orbital_position);
1029 case iDVBFrontend::feTerrestrial:
1031 clearTerrestrial=true;
1034 case iDVBFrontend::feCable:
1043 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
1045 if (m_flags & scanDontRemoveUnscanned)
1046 db->removeServices(&(*(*it)));
1050 (*it)->getSystem(system);
1053 case iDVBFrontend::feSatellite:
1055 eDVBFrontendParametersSatellite sat_parm;
1056 (*it)->getDVBS(sat_parm);
1057 scanned_sat_positions.insert(sat_parm.orbital_position);
1060 case iDVBFrontend::feTerrestrial:
1062 clearTerrestrial=true;
1065 case iDVBFrontend::feCable:
1074 if (clearTerrestrial)
1077 chid.dvbnamespace=0xEEEE0000;
1078 db->removeServices(chid);
1083 chid.dvbnamespace=0xFFFF0000;
1084 db->removeServices(chid);
1086 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
1089 if (m_flags & scanDontRemoveFeeds)
1090 chid.dvbnamespace = eDVBNamespace((*x)<<16);
1091 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
1092 db->removeServices(chid, *x);
1096 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
1097 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
1100 ch->second->getSystem(system);
1101 std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
1105 case iDVBFrontend::feTerrestrial:
1107 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
1108 eDVBFrontendParametersTerrestrial parm;
1109 int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
1111 // eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
1112 // ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
1113 // ch->first.dvbnamespace.get(), freq, parm.frequency);
1114 parm.frequency = freq;
1118 case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
1119 case iDVBFrontend::feCable:
1123 if (m_flags & scanOnlyFree)
1125 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
1126 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
1129 db->addChannelToList(ch->first, ch->second);
1132 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
1133 service(m_new_services.begin()); service != m_new_services.end(); ++service)
1135 ePtr<eDVBService> dvb_service;
1136 if (!db->getService(service->first, dvb_service))
1138 if (dvb_service->m_flags & eDVBService::dxNoSDT)
1140 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
1142 dvb_service->m_service_name = service->second->m_service_name;
1143 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
1145 dvb_service->m_provider_name = service->second->m_provider_name;
1146 if (service->second->m_ca.size())
1147 dvb_service->m_ca = service->second->m_ca;
1148 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
1149 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1153 db->addService(service->first, service->second);
1154 if (!(m_flags & scanRemoveServices))
1155 service->second->m_flags |= eDVBService::dxNewFound;
1160 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1162 const ServiceDescriptionList &services = *sdt.getDescriptions();
1163 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1164 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1166 /* save correct CHID for this channel */
1167 m_chid_current = chid;
1169 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1171 unsigned short service_id = (*s)->getServiceId();
1172 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1175 if (m_flags & scanOnlyFree)
1177 std::map<unsigned short, service>::iterator it =
1178 m_pmts_to_read.find(service_id);
1179 if (it != m_pmts_to_read.end())
1181 if (it->second.scrambled)
1183 SCAN_eDebug("is scrambled!");
1187 SCAN_eDebug("is free");
1190 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1197 eServiceReferenceDVB ref;
1198 ePtr<eDVBService> service = new eDVBService;
1201 ref.setServiceID(service_id);
1203 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1204 desc != (*s)->getDescriptors()->end(); ++desc)
1206 switch ((*desc)->getTag())
1208 case SERVICE_DESCRIPTOR:
1210 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1211 ref.setServiceType(d.getServiceType());
1212 service->m_service_name = convertDVBUTF8(d.getServiceName());
1213 service->genSortName();
1215 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1216 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1219 case CA_IDENTIFIER_DESCRIPTOR:
1221 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1222 const CaSystemIdList &caids = *d.getCaSystemIds();
1223 SCAN_eDebugNoNewLine("CA ");
1224 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1226 SCAN_eDebugNoNewLine("%04x ", *i);
1227 service->m_ca.push_front(*i);
1233 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1238 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1239 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1243 m_last_service = i.first;
1244 m_event(evtNewService);
1247 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1248 m_abort_current_pmt = true;
1250 m_pmts_to_read.erase(service_id);
1256 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1258 connection = new eConnection(this, m_event.connect(event));
1262 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1264 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1265 transponders_total = m_ch_toScan.size() + transponders_done;
1266 services = m_new_services.size();
1269 void eDVBScan::getLastServiceName(std::string &last_service_name)
1271 if (m_last_service == m_new_services.end())
1272 last_service_name = "";
1274 last_service_name = m_last_service->second->m_service_name;
1277 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1280 return m_channel->getFrontend(fe);
1285 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)