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("%d channels scanned, %d were unavailable.",
197 m_ch_scanned.size(), m_ch_unavailable.size());
198 SCAN_eDebug("%d 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 0x10: // MPEG 4 Part 2
385 case 0x01: // MPEG 1 video
386 case 0x02: // MPEG 2 video
389 //break; fall through !!!
390 case 0x03: // MPEG 1 audio
391 case 0x04: // MPEG 2 audio
392 case 0x0f: // MPEG 2 AAC
393 case 0x11: // MPEG 4 AAC
399 case 0x06: // PES Private
400 case 0x81: // user private
401 case 0xEA: // TS_PSI_ST_SMPTE_VC1
402 for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
403 desc != (*es)->getDescriptors()->end(); ++desc)
405 uint8_t tag = (*desc)->getTag();
406 /* PES private can contain AC-3, DTS or lots of other stuff.
407 check descriptors to get the exakt type. */
408 if (!forced_video && !forced_audio)
412 case 0x1C: // TS_PSI_DT_MPEG4_Audio
413 case 0x2B: // TS_PSI_DT_MPEG2_AAC
417 case AUDIO_STREAM_DESCRIPTOR:
420 case 0x28: // TS_PSI_DT_AVC
421 case 0x1B: // TS_PSI_DT_MPEG4_Video
422 case VIDEO_STREAM_DESCRIPTOR:
425 case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
427 RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc);
428 switch (d->getFormatIdentifier())
430 case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
431 case 0x41432d33: // == 'AC-3'
432 case 0x42535344: // == 'BSSD' (LPCM)
435 case 0x56432d31: // == 'VC-1'
446 if (tag == CA_DESCRIPTOR)
461 for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
462 desc != pmt.getDescriptors()->end(); ++desc)
464 if ((*desc)->getTag() == CA_DESCRIPTOR)
468 m_pmt_in_progress->second.scrambled = scrambled;
470 m_pmt_in_progress->second.serviceType = 1;
471 else if ( have_audio )
472 m_pmt_in_progress->second.serviceType = 2;
474 m_pmt_in_progress->second.serviceType = 100;
476 if (err == -1) // timeout or removed by sdt
477 m_pmts_to_read.erase(m_pmt_in_progress++);
478 else if (m_pmt_running)
482 m_pmt_in_progress = m_pmts_to_read.begin();
483 m_pmt_running = true;
486 if (m_pmt_in_progress != m_pmts_to_read.end())
487 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
491 m_pmt_running = false;
497 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
499 /* add it to the list of known channels. */
501 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
504 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
506 /* check if we don't already have that channel ... */
509 feparm->getSystem(type);
513 case iDVBFrontend::feSatellite:
515 eDVBFrontendParametersSatellite parm;
516 feparm->getDVBS(parm);
517 SCAN_eDebug("try to add %d %d %d %d %d %d",
518 parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
521 case iDVBFrontend::feCable:
523 eDVBFrontendParametersCable parm;
524 feparm->getDVBC(parm);
525 SCAN_eDebug("try to add %d %d %d %d",
526 parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
529 case iDVBFrontend::feTerrestrial:
531 eDVBFrontendParametersTerrestrial parm;
532 feparm->getDVBT(parm);
533 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
534 parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
535 parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
541 /* ... in the list of channels to scan */
542 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
544 if (sameChannel(*i, feparm))
548 *i = feparm; // update
549 SCAN_eDebug("update");
553 SCAN_eDebug("remove dupe");
554 m_ch_toScan.erase(i++);
564 SCAN_eDebug("already in todo list");
568 /* ... in the list of successfully scanned channels */
569 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
570 if (sameChannel(*i, feparm))
572 SCAN_eDebug("successfully scanned");
576 /* ... in the list of unavailable channels */
577 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
578 if (sameChannel(*i, feparm, true))
580 SCAN_eDebug("scanned but not available");
584 /* ... on the current channel */
585 if (sameChannel(m_ch_current, feparm))
587 SCAN_eDebug("is current");
591 SCAN_eDebug("really add");
592 /* otherwise, add it to the todo list. */
593 m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
596 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
599 if (ch1->calculateDifference(ch2, diff, exact))
601 if (diff < 4000) // more than 4mhz difference?
606 void eDVBScan::channelDone()
608 if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
610 unsigned long hash = 0;
612 m_ch_current->getHash(hash);
614 eDVBNamespace dvbnamespace = buildNamespace(
615 (**m_SDT->getSections().begin()).getOriginalNetworkId(),
616 (**m_SDT->getSections().begin()).getTransportStreamId(),
619 SCAN_eDebug("SDT: ");
620 std::vector<ServiceDescriptionSection*>::const_iterator i;
621 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
622 processSDT(dvbnamespace, **i);
623 m_ready &= ~validSDT;
626 if (m_ready & validNIT)
629 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
630 m_ch_current->getSystem(system);
631 SCAN_eDebug("dumping NIT");
632 if (m_flags & clearToScanOnFirstNIT)
634 m_ch_toScan_backup = m_ch_toScan;
637 std::vector<NetworkInformationSection*>::const_iterator i;
638 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
640 const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
642 for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin());
643 tsinfo != tsinfovec.end(); ++tsinfo)
645 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
646 (*tsinfo)->getOriginalNetworkId());
648 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
649 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
651 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
652 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
654 switch ((*desc)->getTag())
656 case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
658 if (system != iDVBFrontend::feCable)
659 break; // when current locked transponder is no cable transponder ignore this descriptor
660 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
661 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
662 eDVBFrontendParametersCable cable;
664 feparm->setDVBC(cable);
666 unsigned long hash=0;
667 feparm->getHash(hash);
668 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
671 eDVBChannelID(ns, tsid, onid),
675 case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
677 if (system != iDVBFrontend::feTerrestrial)
678 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
679 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
680 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
681 eDVBFrontendParametersTerrestrial terr;
683 feparm->setDVBT(terr);
685 unsigned long hash=0;
686 feparm->getHash(hash);
687 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
690 eDVBChannelID(ns, tsid, onid),
694 case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
696 if (system != iDVBFrontend::feSatellite)
697 break; // when current locked transponder is no satellite transponder ignore this descriptor
699 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
700 if (d.getFrequency() < 10000)
703 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
704 eDVBFrontendParametersSatellite sat;
707 eDVBFrontendParametersSatellite p;
708 m_ch_current->getDVBS(p);
710 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
711 sat.orbital_position = p.orbital_position;
713 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
715 SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
716 sat.orbital_position = p.orbital_position;
719 feparm->setDVBS(sat);
721 if ( p.orbital_position != sat.orbital_position)
722 SCAN_eDebug("dropping this transponder, it's on another satellite.");
725 unsigned long hash=0;
726 feparm->getHash(hash);
728 eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
734 SCAN_eDebug("descr<%x>", (*desc)->getTag());
742 /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
743 no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
746 This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
748 if (m_flags & clearToScanOnFirstNIT)
750 if (m_ch_toScan.empty())
752 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
753 m_ch_toScan = m_ch_toScan_backup;
755 m_flags &= ~clearToScanOnFirstNIT;
757 m_ready &= ~validNIT;
760 if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
762 if (m_abort_current_pmt)
764 m_abort_current_pmt = false;
770 SCAN_eDebug("channel done!");
772 /* if we had services on this channel, we declare
773 this channels as "known good". add it.
775 (TODO: not yet implemented)
776 a NIT entry could have possible overridden
777 our frontend data with more exact data.
779 (TODO: not yet implemented)
780 the tuning process could have lead to more
781 exact data than the user entered.
783 The channel id was probably corrected
784 by the data written in the SDT. this is
785 important, as "initial transponder lists"
786 usually don't have valid CHIDs (and that's
789 These are the reasons for adding the transponder
790 here, and not before.
794 if (m_ch_current->getSystem(type))
797 for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
799 eServiceReferenceDVB ref;
800 ePtr<eDVBService> service = new eDVBService;
804 unsigned long hash = 0;
806 m_ch_current->getHash(hash);
808 m_chid_current = eDVBChannelID(
809 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
810 m_pat_tsid, eOriginalNetworkID(0));
813 if (m_pmt_in_progress->second.serviceType == 1)
814 SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
815 else if (m_pmt_in_progress->second.serviceType == 2)
816 SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
818 SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
820 ref.set(m_chid_current);
821 ref.setServiceID(m_pmt_in_progress->first);
822 ref.setServiceType(m_pmt_in_progress->second.serviceType);
828 memset(pname, 0, sizeof(pname));
829 memset(sname, 0, sizeof(sname));
832 case iDVBFrontend::feSatellite:
834 eDVBFrontendParametersSatellite parm;
835 m_ch_current->getDVBS(parm);
836 snprintf(sname, 255, "%d%c SID 0x%02x",
838 parm.polarisation ? 'V' : 'H',
839 m_pmt_in_progress->first);
840 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
841 parm.system ? "DVB-S2" : "DVB-S",
842 parm.modulation == 1 ? "QPSK" : "8PSK",
844 parm.polarisation ? 'V' : 'H',
845 parm.orbital_position/10,
846 parm.orbital_position%10,
847 parm.orbital_position > 0 ? 'E' : 'W');
850 case iDVBFrontend::feTerrestrial:
852 eDVBFrontendParametersTerrestrial parm;
853 m_ch_current->getDVBT(parm);
854 snprintf(sname, 255, "%d SID 0x%02x",
856 m_pmt_in_progress->first);
859 case iDVBFrontend::feCable:
861 eDVBFrontendParametersCable parm;
862 m_ch_current->getDVBC(parm);
863 snprintf(sname, 255, "%d SID 0x%02x",
865 m_pmt_in_progress->first);
869 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
870 service->m_service_name = convertDVBUTF8(sname);
871 service->genSortName();
872 service->m_provider_name = convertDVBUTF8(pname);
875 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
876 SCAN_eDebug("add not scrambled!");
877 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
878 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
881 m_last_service = i.first;
882 m_event(evtNewService);
886 SCAN_eDebug("dont add... is scrambled!");
887 m_pmts_to_read.erase(m_pmt_in_progress++);
891 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
894 addKnownGoodChannel(m_chid_current, m_ch_current);
899 case iDVBFrontend::feSatellite:
900 case iDVBFrontend::feTerrestrial:
901 case iDVBFrontend::feCable:
903 ePtr<iDVBFrontend> fe;
904 if (!m_channel->getFrontend(fe))
906 ePyObject tp_dict = PyDict_New();
907 fe->getTransponderData(tp_dict, false);
908 // eDebug("add tuner data for tsid %04x, onid %04x, ns %08x",
909 // m_chid_current.transport_stream_id.get(), m_chid_current.original_network_id.get(),
910 // m_chid_current.dvbnamespace.get());
911 m_tuner_data.insert(std::pair<eDVBChannelID, ePyObjectWrapper>(m_chid_current, tp_dict));
921 m_ch_scanned.push_back(m_ch_current);
923 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
925 if (sameChannel(*i, m_ch_current))
927 SCAN_eDebug("remove dupe 2");
928 m_ch_toScan.erase(i++);
937 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
941 m_ch_scanned.clear();
942 m_ch_unavailable.clear();
943 m_new_channels.clear();
944 m_tuner_data.clear();
945 m_new_services.clear();
946 m_last_service = m_new_services.end();
948 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
951 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
953 if (sameChannel(*i, *ii, true))
960 m_ch_toScan.push_back(*i);
966 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
968 if (m_flags & scanRemoveServices)
970 bool clearTerrestrial=false;
971 bool clearCable=false;
972 std::set<unsigned int> scanned_sat_positions;
974 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
975 for (;it != m_ch_scanned.end(); ++it)
977 if (m_flags & scanDontRemoveUnscanned)
978 db->removeServices(&(*(*it)));
982 (*it)->getSystem(system);
985 case iDVBFrontend::feSatellite:
987 eDVBFrontendParametersSatellite sat_parm;
988 (*it)->getDVBS(sat_parm);
989 scanned_sat_positions.insert(sat_parm.orbital_position);
992 case iDVBFrontend::feTerrestrial:
994 clearTerrestrial=true;
997 case iDVBFrontend::feCable:
1006 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
1008 if (m_flags & scanDontRemoveUnscanned)
1009 db->removeServices(&(*(*it)));
1013 (*it)->getSystem(system);
1016 case iDVBFrontend::feSatellite:
1018 eDVBFrontendParametersSatellite sat_parm;
1019 (*it)->getDVBS(sat_parm);
1020 scanned_sat_positions.insert(sat_parm.orbital_position);
1023 case iDVBFrontend::feTerrestrial:
1025 clearTerrestrial=true;
1028 case iDVBFrontend::feCable:
1037 if (clearTerrestrial)
1040 chid.dvbnamespace=0xEEEE0000;
1041 db->removeServices(chid);
1046 chid.dvbnamespace=0xFFFF0000;
1047 db->removeServices(chid);
1049 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
1052 if (m_flags & scanDontRemoveFeeds)
1053 chid.dvbnamespace = eDVBNamespace((*x)<<16);
1054 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
1055 db->removeServices(chid, *x);
1059 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
1060 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
1063 ch->second->getSystem(system);
1064 std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
1068 case iDVBFrontend::feTerrestrial:
1070 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
1071 eDVBFrontendParametersTerrestrial parm;
1072 int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
1074 // eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
1075 // ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
1076 // ch->first.dvbnamespace.get(), freq, parm.frequency);
1077 parm.frequency = freq;
1081 case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
1082 case iDVBFrontend::feCable:
1086 if (m_flags & scanOnlyFree)
1088 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
1089 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
1092 db->addChannelToList(ch->first, ch->second);
1095 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
1096 service(m_new_services.begin()); service != m_new_services.end(); ++service)
1098 ePtr<eDVBService> dvb_service;
1099 if (!db->getService(service->first, dvb_service))
1101 if (dvb_service->m_flags & eDVBService::dxNoSDT)
1103 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
1105 dvb_service->m_service_name = service->second->m_service_name;
1106 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
1108 dvb_service->m_provider_name = service->second->m_provider_name;
1109 if (service->second->m_ca.size())
1110 dvb_service->m_ca = service->second->m_ca;
1111 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
1112 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1116 db->addService(service->first, service->second);
1117 if (!(m_flags & scanRemoveServices))
1118 service->second->m_flags |= eDVBService::dxNewFound;
1123 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1125 const ServiceDescriptionList &services = *sdt.getDescriptions();
1126 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1127 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1129 /* save correct CHID for this channel */
1130 m_chid_current = chid;
1132 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1134 unsigned short service_id = (*s)->getServiceId();
1135 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1138 if (m_flags & scanOnlyFree)
1140 std::map<unsigned short, service>::iterator it =
1141 m_pmts_to_read.find(service_id);
1142 if (it != m_pmts_to_read.end())
1144 if (it->second.scrambled)
1146 SCAN_eDebug("is scrambled!");
1150 SCAN_eDebug("is free");
1153 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1160 eServiceReferenceDVB ref;
1161 ePtr<eDVBService> service = new eDVBService;
1164 ref.setServiceID(service_id);
1166 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1167 desc != (*s)->getDescriptors()->end(); ++desc)
1169 switch ((*desc)->getTag())
1171 case SERVICE_DESCRIPTOR:
1173 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1174 ref.setServiceType(d.getServiceType());
1175 service->m_service_name = convertDVBUTF8(d.getServiceName());
1176 service->genSortName();
1178 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1179 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1182 case CA_IDENTIFIER_DESCRIPTOR:
1184 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1185 const CaSystemIdList &caids = *d.getCaSystemIds();
1186 SCAN_eDebugNoNewLine("CA ");
1187 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1189 SCAN_eDebugNoNewLine("%04x ", *i);
1190 service->m_ca.push_front(*i);
1196 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1201 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1202 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1206 m_last_service = i.first;
1207 m_event(evtNewService);
1210 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1211 m_abort_current_pmt = true;
1213 m_pmts_to_read.erase(service_id);
1219 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1221 connection = new eConnection(this, m_event.connect(event));
1225 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1227 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1228 transponders_total = m_ch_toScan.size() + transponders_done;
1229 services = m_new_services.size();
1232 void eDVBScan::getLastServiceName(std::string &last_service_name)
1234 if (m_last_service == m_new_services.end())
1235 last_service_name = "";
1237 last_service_name = m_last_service->second->m_service_name;
1240 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1243 return m_channel->getFrontend(fe);
1248 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)