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 char system_name[255];
872 char modulation_name[255];
873 memset(system_name, 0, sizeof(system_name));
874 memset(modulation_name, 0, sizeof(modulation_name));
876 eDVBFrontendParametersSatellite parm;
877 m_ch_current->getDVBS(parm);
879 if (parm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
880 strcpy(system_name, "DVB-S2");
881 else if (parm.system == eDVBFrontendParametersSatellite::System_DVB_S2X)
882 strcpy(system_name, "DVB-S2X");
884 strcpy(system_name, "DVB-S");
886 if (parm.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
887 strcpy(modulation_name, "QPSK");
888 else if (parm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
889 strcpy(modulation_name, "8PSK");
890 else if (parm.modulation == eDVBFrontendParametersSatellite::Modulation_8APSK)
891 strcpy(modulation_name, "8APSK");
892 else if (parm.modulation == eDVBFrontendParametersSatellite::Modulation_16APSK)
893 strcpy(modulation_name, "16APSK");
894 else if (parm.modulation == eDVBFrontendParametersSatellite::Modulation_32APSK)
895 strcpy(modulation_name, "32APSK");
897 strcpy(modulation_name, "8PSK");
899 snprintf(sname, 255, "%d%c SID 0x%02x",
901 parm.polarisation ? 'V' : 'H',
902 m_pmt_in_progress->first);
903 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
907 parm.polarisation ? 'V' : 'H',
908 parm.orbital_position/10,
909 parm.orbital_position%10,
910 parm.orbital_position > 0 ? 'E' : 'W');
913 case iDVBFrontend::feTerrestrial:
915 eDVBFrontendParametersTerrestrial parm;
916 m_ch_current->getDVBT(parm);
917 snprintf(sname, 255, "%d SID 0x%02x",
919 m_pmt_in_progress->first);
922 case iDVBFrontend::feCable:
924 eDVBFrontendParametersCable parm;
925 m_ch_current->getDVBC(parm);
926 snprintf(sname, 255, "%d SID 0x%02x",
928 m_pmt_in_progress->first);
932 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
933 service->m_service_name = convertDVBUTF8(sname);
934 service->genSortName();
935 service->m_provider_name = convertDVBUTF8(pname);
938 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
939 SCAN_eDebug("add not scrambled!");
940 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
941 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
944 m_last_service = i.first;
945 m_event(evtNewService);
949 SCAN_eDebug("dont add... is scrambled!");
950 m_pmts_to_read.erase(m_pmt_in_progress++);
954 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
957 addKnownGoodChannel(m_chid_current, m_ch_current);
962 case iDVBFrontend::feSatellite:
963 case iDVBFrontend::feTerrestrial:
964 case iDVBFrontend::feCable:
966 ePtr<iDVBFrontend> fe;
967 if (!m_channel->getFrontend(fe))
969 ePyObject tp_dict = PyDict_New();
970 fe->getTransponderData(tp_dict, false);
971 // eDebug("add tuner data for tsid %04x, onid %04x, ns %08x",
972 // m_chid_current.transport_stream_id.get(), m_chid_current.original_network_id.get(),
973 // m_chid_current.dvbnamespace.get());
974 m_tuner_data.insert(std::pair<eDVBChannelID, ePyObjectWrapper>(m_chid_current, tp_dict));
984 m_ch_scanned.push_back(m_ch_current);
986 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
988 if (sameChannel(*i, m_ch_current))
990 SCAN_eDebug("remove dupe 2");
991 m_ch_toScan.erase(i++);
1000 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
1003 m_ch_toScan.clear();
1004 m_ch_scanned.clear();
1005 m_ch_unavailable.clear();
1006 m_new_channels.clear();
1007 m_tuner_data.clear();
1008 m_new_services.clear();
1009 m_last_service = m_new_services.end();
1011 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
1014 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
1016 if (sameChannel(*i, *ii, true))
1023 m_ch_toScan.push_back(*i);
1029 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
1031 if (m_flags & scanRemoveServices)
1033 bool clearTerrestrial=false;
1034 bool clearCable=false;
1035 std::set<unsigned int> scanned_sat_positions;
1037 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
1038 for (;it != m_ch_scanned.end(); ++it)
1040 if (m_flags & scanDontRemoveUnscanned)
1041 db->removeServices(&(*(*it)));
1045 (*it)->getSystem(system);
1048 case iDVBFrontend::feSatellite:
1050 eDVBFrontendParametersSatellite sat_parm;
1051 (*it)->getDVBS(sat_parm);
1052 scanned_sat_positions.insert(sat_parm.orbital_position);
1055 case iDVBFrontend::feTerrestrial:
1057 clearTerrestrial=true;
1060 case iDVBFrontend::feCable:
1069 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
1071 if (m_flags & scanDontRemoveUnscanned)
1072 db->removeServices(&(*(*it)));
1076 (*it)->getSystem(system);
1079 case iDVBFrontend::feSatellite:
1081 eDVBFrontendParametersSatellite sat_parm;
1082 (*it)->getDVBS(sat_parm);
1083 scanned_sat_positions.insert(sat_parm.orbital_position);
1086 case iDVBFrontend::feTerrestrial:
1088 clearTerrestrial=true;
1091 case iDVBFrontend::feCable:
1100 if (clearTerrestrial)
1103 chid.dvbnamespace=0xEEEE0000;
1104 db->removeServices(chid);
1109 chid.dvbnamespace=0xFFFF0000;
1110 db->removeServices(chid);
1112 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
1115 if (m_flags & scanDontRemoveFeeds)
1116 chid.dvbnamespace = eDVBNamespace((*x)<<16);
1117 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
1118 db->removeServices(chid, *x);
1122 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
1123 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
1126 ch->second->getSystem(system);
1127 std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
1131 case iDVBFrontend::feTerrestrial:
1133 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
1134 eDVBFrontendParametersTerrestrial parm;
1135 int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
1137 // eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
1138 // ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
1139 // ch->first.dvbnamespace.get(), freq, parm.frequency);
1140 parm.frequency = freq;
1144 case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
1145 case iDVBFrontend::feCable:
1149 if (m_flags & scanOnlyFree)
1151 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
1152 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
1155 db->addChannelToList(ch->first, ch->second);
1158 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
1159 service(m_new_services.begin()); service != m_new_services.end(); ++service)
1161 ePtr<eDVBService> dvb_service;
1162 if (!db->getService(service->first, dvb_service))
1164 if (dvb_service->m_flags & eDVBService::dxNoSDT)
1166 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
1168 dvb_service->m_service_name = service->second->m_service_name;
1169 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
1171 dvb_service->m_provider_name = service->second->m_provider_name;
1172 if (service->second->m_ca.size())
1173 dvb_service->m_ca = service->second->m_ca;
1174 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
1175 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1179 db->addService(service->first, service->second);
1180 if (!(m_flags & scanRemoveServices))
1181 service->second->m_flags |= eDVBService::dxNewFound;
1186 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1188 const ServiceDescriptionList &services = *sdt.getDescriptions();
1189 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1190 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1192 /* save correct CHID for this channel */
1193 m_chid_current = chid;
1195 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1197 unsigned short service_id = (*s)->getServiceId();
1198 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1201 if (m_flags & scanOnlyFree)
1203 std::map<unsigned short, service>::iterator it =
1204 m_pmts_to_read.find(service_id);
1205 if (it != m_pmts_to_read.end())
1207 if (it->second.scrambled)
1209 SCAN_eDebug("is scrambled!");
1213 SCAN_eDebug("is free");
1216 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1223 eServiceReferenceDVB ref;
1224 ePtr<eDVBService> service = new eDVBService;
1227 ref.setServiceID(service_id);
1229 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1230 desc != (*s)->getDescriptors()->end(); ++desc)
1232 switch ((*desc)->getTag())
1234 case SERVICE_DESCRIPTOR:
1236 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1237 ref.setServiceType(d.getServiceType());
1238 service->m_service_name = convertDVBUTF8(d.getServiceName());
1239 service->genSortName();
1241 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1242 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1245 case CA_IDENTIFIER_DESCRIPTOR:
1247 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1248 const CaSystemIdList &caids = *d.getCaSystemIds();
1249 SCAN_eDebugNoNewLine("CA ");
1250 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1252 SCAN_eDebugNoNewLine("%04x ", *i);
1253 service->m_ca.push_front(*i);
1259 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1264 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1265 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1269 m_last_service = i.first;
1270 m_event(evtNewService);
1273 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1274 m_abort_current_pmt = true;
1276 m_pmts_to_read.erase(service_id);
1282 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1284 connection = new eConnection(this, m_event.connect(event));
1288 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1290 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1291 transponders_total = m_ch_toScan.size() + transponders_done;
1292 services = m_new_services.size();
1295 void eDVBScan::getLastServiceName(std::string &last_service_name)
1297 if (m_last_service == m_new_services.end())
1298 last_service_name = "";
1300 last_service_name = m_last_service->second->m_service_name;
1303 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1306 return m_channel->getFrontend(fe);
1311 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)