1 #include <lib/dvb/idvb.h>
2 #include <dvbsi++/descriptor_tag.h>
3 #include <dvbsi++/service_descriptor.h>
4 #include <dvbsi++/satellite_delivery_system_descriptor.h>
5 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
6 #include <dvbsi++/cable_delivery_system_descriptor.h>
7 #include <dvbsi++/ca_identifier_descriptor.h>
8 #include <dvbsi++/registration_descriptor.h>
9 #include <lib/dvb/specs.h>
10 #include <lib/dvb/esection.h>
11 #include <lib/dvb/scan.h>
12 #include <lib/dvb/frontend.h>
13 #include <lib/base/eerror.h>
14 #include <lib/base/estring.h>
15 #include <lib/python/python.h>
18 #define SCAN_eDebug(x...) do { if (m_scan_debug) eDebug(x); } while(0)
19 #define SCAN_eDebugNoNewLine(x...) do { if (m_scan_debug) eDebugNoNewLine(x); } while(0)
23 eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug)
24 :m_channel(channel), m_channel_state(iDVBChannel::state_idle)
25 ,m_ready(0), m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT)
26 ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0)
27 ,m_usePAT(usePAT), m_scan_debug(debug), m_show_add_tsid_onid_check_failed_msg(true)
29 if (m_channel->getDemux(m_demux))
30 SCAN_eDebug("scan: failed to allocate demux!");
31 m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
32 FILE *f = fopen("/etc/enigma2/scan_tp_valid_check.py", "r");
36 size_t rd = fread(code, 1, 16383, f);
40 m_additional_tsid_onid_check_func = Py_CompileString(code, "/etc/enigma2/scan_tp_valid_check.py", Py_file_input);
48 if (m_additional_tsid_onid_check_func)
49 Py_DECREF(m_additional_tsid_onid_check_func);
52 int eDVBScan::isValidONIDTSID(int orbital_position, eOriginalNetworkID onid, eTransportStreamID tsid)
61 case 0x13E: // workaround for 11258H and 11470V on hotbird with same ONID/TSID (0x13E/0x578)
62 ret = orbital_position != 130 || tsid != 0x578;
65 ret = orbital_position == 192;
74 ret = abs(orbital_position-282) < 6 && tsid != 2019;
75 // 12070H and 10936V have same tsid/onid.. but even the same services are provided
80 case 0x5E: // Sirius 4.8E 12322V and 12226H
81 ret = abs(orbital_position-48) < 3 && tsid != 1;
83 case 10100: // Eutelsat W7 36.0E 11644V and 11652V
84 ret = orbital_position != 360 || tsid != 10187;
86 case 42: // Tuerksat 42.0E
87 ret = orbital_position != 420 || (
88 tsid != 8 && // 11830V 12729V
89 tsid != 5 && // 12679V 12685H
90 tsid != 2 && // 11096V 12015H
91 tsid != 55); // 11996V 11716V
93 case 100: // Intelsat 10 68.5E 3808V 3796V 4012V, Amos 4.0W 10723V 11571H
94 ret = (orbital_position != 685 && orbital_position != 3560) || tsid != 1;
96 case 70: // Thor 0.8W 11862H 12341V
97 ret = abs(orbital_position-3592) < 3 && tsid != 46;
99 case 32: // NSS 806 (40.5W) 4059R, 3774L
100 ret = orbital_position != 3195 || tsid != 21;
103 ret = onid.get() < 0xFF00;
106 if (ret && m_additional_tsid_onid_check_func)
109 ePyObject dict = PyDict_New();
110 extern void PutToDict(ePyObject &, const char *, long);
111 PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
112 PutToDict(dict, "orbpos", orbital_position);
113 PutToDict(dict, "tsid", tsid.get());
114 PutToDict(dict, "onid", onid.get());
115 ePyObject r = PyEval_EvalCode((PyCodeObject*)(PyObject*)m_additional_tsid_onid_check_func, dict, dict);
118 ePyObject o = PyDict_GetItemString(dict, "ret");
123 ret = PyInt_AsLong(o);
129 if (failed && m_show_add_tsid_onid_check_failed_msg)
131 eDebug("execing /etc/enigma2/scan_tp_valid_check failed!\n"
132 "usable global variables in scan_tp_valid_check.py are 'orbpos', 'tsid', 'onid'\n"
133 "the return value must be stored in a global var named 'ret'");
134 m_show_add_tsid_onid_check_failed_msg=false;
141 eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash)
143 // on valid ONIDs, ignore frequency ("sub network") part
144 if (isValidONIDTSID((hash >> 16) & 0xFFFF, onid, tsid))
146 return eDVBNamespace(hash);
149 void eDVBScan::stateChange(iDVBChannel *ch)
152 if (ch->getState(state))
154 if (m_channel_state == state)
157 if (state == iDVBChannel::state_ok)
160 m_channel_state = state;
161 } else if (state == iDVBChannel::state_failed)
163 m_ch_unavailable.push_back(m_ch_current);
166 /* unavailable will timeout, anyway. */
169 RESULT eDVBScan::nextChannel()
171 ePtr<iDVBFrontend> fe;
173 m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0;
177 m_pat_tsid = eTransportStreamID();
179 /* check what we need */
180 m_ready_all = readySDT;
182 if (m_flags & scanNetworkSearch)
183 m_ready_all |= readyNIT;
185 if (m_flags & scanSearchBAT)
186 m_ready_all |= readyBAT;
189 m_ready_all |= readyPAT;
191 if (m_ch_toScan.empty())
193 SCAN_eDebug("no channels left to scan.");
194 SCAN_eDebug("%d channels scanned, %d were unavailable.",
195 m_ch_scanned.size(), m_ch_unavailable.size());
196 SCAN_eDebug("%d channels in database.", m_new_channels.size());
201 m_ch_current = m_ch_toScan.front();
203 m_ch_toScan.pop_front();
205 if (m_channel->getFrontend(fe))
211 m_chid_current = eDVBChannelID();
213 m_channel_state = iDVBChannel::state_idle;
215 if (fe->tune(*m_ch_current))
216 return nextChannel();
222 RESULT eDVBScan::startFilter()
227 /* only start required filters filter */
229 if (m_ready_all & readyPAT)
230 startSDT = m_ready & readyPAT;
232 // m_ch_current is not set, when eDVBScan is just used for a SDT update
235 unsigned int channelFlags;
236 m_channel->getCurrentFrontendParameters(m_ch_current);
237 m_ch_current->getFlags(channelFlags);
238 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
239 m_flags |= scanOnlyFree;
243 if (startSDT && (m_ready_all & readySDT))
245 m_SDT = new eTable<ServiceDescriptionSection>(m_scan_debug);
247 if (m_ready & readyPAT && m_ready & validPAT)
249 std::vector<ProgramAssociationSection*>::const_iterator i =
250 m_PAT->getSections().begin();
251 ASSERT(i != m_PAT->getSections().end());
252 tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
253 m_pat_tsid = eTransportStreamID(tsid);
254 for (; i != m_PAT->getSections().end(); ++i)
256 const ProgramAssociationSection &pat = **i;
257 ProgramAssociationConstIterator program = pat.getPrograms()->begin();
258 for (; program != pat.getPrograms()->end(); ++program)
259 m_pmts_to_read.insert(std::pair<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
261 m_PMT = new eTable<ProgramMapSection>(m_scan_debug);
262 CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
264 // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
268 m_ch_current->getSystem(type);
269 if (type == iDVBFrontend::feCable)
271 eDVBFrontendParametersCable parm;
272 m_ch_current->getDVBC(parm);
273 if ((tsid == 0x00d7 && abs(parm.frequency-618000) < 2000) ||
274 (tsid == 0x00d8 && abs(parm.frequency-626000) < 2000))
281 if (m_SDT->start(m_demux, eDVBSDTSpec()))
284 else if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
286 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
289 if (!(m_ready & readyPAT))
292 if (m_ready_all & readyPAT)
294 m_PAT = new eTable<ProgramAssociationSection>(m_scan_debug);
295 if (m_PAT->start(m_demux, eDVBPATSpec(4000)))
297 CONNECT(m_PAT->tableReady, eDVBScan::PATready);
301 if (m_ready_all & readyNIT)
303 m_NIT = new eTable<NetworkInformationSection>(m_scan_debug);
304 if (m_NIT->start(m_demux, eDVBNITSpec()))
306 CONNECT(m_NIT->tableReady, eDVBScan::NITready);
310 if (m_ready_all & readyBAT)
312 m_BAT = new eTable<BouquetAssociationSection>(m_scan_debug);
313 if (m_BAT->start(m_demux, eDVBBATSpec()))
315 CONNECT(m_BAT->tableReady, eDVBScan::BATready);
321 void eDVBScan::SDTready(int err)
323 SCAN_eDebug("got sdt %d", err);
330 void eDVBScan::NITready(int err)
332 SCAN_eDebug("got nit, err %d", err);
339 void eDVBScan::BATready(int err)
341 SCAN_eDebug("got bat");
348 void eDVBScan::PATready(int err)
350 SCAN_eDebug("got pat");
354 startFilter(); // for starting the SDT filter
357 void eDVBScan::PMTready(int err)
359 SCAN_eDebug("got pmt %d", err);
362 bool scrambled = false;
363 bool have_audio = false;
364 bool have_video = false;
365 unsigned short pcrpid = 0xFFFF;
366 std::vector<ProgramMapSection*>::const_iterator i;
368 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
370 const ProgramMapSection &pmt = **i;
371 if (pcrpid == 0xFFFF)
372 pcrpid = pmt.getPcrPid();
374 SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
375 ElementaryStreamInfoConstIterator es;
376 for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
378 int isaudio = 0, isvideo = 0, is_scrambled = 0, forced_audio = 0, forced_video = 0;
379 switch ((*es)->getType())
381 case 0x1b: // AVC Video Stream (MPEG4 H264)
382 case 0x10: // MPEG 4 Part 2
383 case 0x01: // MPEG 1 video
384 case 0x02: // MPEG 2 video
387 //break; fall through !!!
388 case 0x03: // MPEG 1 audio
389 case 0x04: // MPEG 2 audio
390 case 0x0f: // MPEG 2 AAC
391 case 0x11: // MPEG 4 AAC
397 case 0x06: // PES Private
398 case 0x81: // user private
399 case 0xEA: // TS_PSI_ST_SMPTE_VC1
400 for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
401 desc != (*es)->getDescriptors()->end(); ++desc)
403 uint8_t tag = (*desc)->getTag();
404 /* PES private can contain AC-3, DTS or lots of other stuff.
405 check descriptors to get the exakt type. */
406 if (!forced_video && !forced_audio)
410 case 0x1C: // TS_PSI_DT_MPEG4_Audio
411 case 0x2B: // TS_PSI_DT_MPEG2_AAC
415 case AUDIO_STREAM_DESCRIPTOR:
418 case 0x28: // TS_PSI_DT_AVC
419 case 0x1B: // TS_PSI_DT_MPEG4_Video
420 case VIDEO_STREAM_DESCRIPTOR:
423 case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
425 RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc);
426 switch (d->getFormatIdentifier())
428 case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
429 case 0x41432d33: // == 'AC-3'
430 case 0x42535344: // == 'BSSD' (LPCM)
433 case 0x56432d31: // == 'VC-1'
444 if (tag == CA_DESCRIPTOR)
459 for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
460 desc != pmt.getDescriptors()->end(); ++desc)
462 if ((*desc)->getTag() == CA_DESCRIPTOR)
466 m_pmt_in_progress->second.scrambled = scrambled;
468 m_pmt_in_progress->second.serviceType = 1;
469 else if ( have_audio )
470 m_pmt_in_progress->second.serviceType = 2;
472 m_pmt_in_progress->second.serviceType = 100;
474 if (err == -1) // timeout or removed by sdt
475 m_pmts_to_read.erase(m_pmt_in_progress++);
476 else if (m_pmt_running)
480 m_pmt_in_progress = m_pmts_to_read.begin();
481 m_pmt_running = true;
484 if (m_pmt_in_progress != m_pmts_to_read.end())
485 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
489 m_pmt_running = false;
495 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
497 /* add it to the list of known channels. */
499 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
502 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
504 /* check if we don't already have that channel ... */
507 feparm->getSystem(type);
511 case iDVBFrontend::feSatellite:
513 eDVBFrontendParametersSatellite parm;
514 feparm->getDVBS(parm);
515 SCAN_eDebug("try to add %d %d %d %d %d %d",
516 parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
519 case iDVBFrontend::feCable:
521 eDVBFrontendParametersCable parm;
522 feparm->getDVBC(parm);
523 SCAN_eDebug("try to add %d %d %d %d",
524 parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
527 case iDVBFrontend::feTerrestrial:
529 eDVBFrontendParametersTerrestrial parm;
530 feparm->getDVBT(parm);
531 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
532 parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
533 parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
539 /* ... in the list of channels to scan */
540 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
542 if (sameChannel(*i, feparm))
546 *i = feparm; // update
547 SCAN_eDebug("update");
551 SCAN_eDebug("remove dupe");
552 m_ch_toScan.erase(i++);
562 SCAN_eDebug("already in todo list");
566 /* ... in the list of successfully scanned channels */
567 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
568 if (sameChannel(*i, feparm))
570 SCAN_eDebug("successfully scanned");
574 /* ... in the list of unavailable channels */
575 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
576 if (sameChannel(*i, feparm, true))
578 SCAN_eDebug("scanned but not available");
582 /* ... on the current channel */
583 if (sameChannel(m_ch_current, feparm))
585 SCAN_eDebug("is current");
589 SCAN_eDebug("really add");
590 /* otherwise, add it to the todo list. */
591 m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
594 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
597 if (ch1->calculateDifference(ch2, diff, exact))
599 if (diff < 4000) // more than 4mhz difference?
604 void eDVBScan::channelDone()
606 if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
608 unsigned long hash = 0;
610 m_ch_current->getHash(hash);
612 eDVBNamespace dvbnamespace = buildNamespace(
613 (**m_SDT->getSections().begin()).getOriginalNetworkId(),
614 (**m_SDT->getSections().begin()).getTransportStreamId(),
617 SCAN_eDebug("SDT: ");
618 std::vector<ServiceDescriptionSection*>::const_iterator i;
619 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
620 processSDT(dvbnamespace, **i);
621 m_ready &= ~validSDT;
624 if (m_ready & validNIT)
627 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
628 m_ch_current->getSystem(system);
629 SCAN_eDebug("dumping NIT");
630 if (m_flags & clearToScanOnFirstNIT)
632 m_ch_toScan_backup = m_ch_toScan;
635 std::vector<NetworkInformationSection*>::const_iterator i;
636 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
638 const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
640 for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin());
641 tsinfo != tsinfovec.end(); ++tsinfo)
643 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
644 (*tsinfo)->getOriginalNetworkId());
646 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
647 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
649 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
650 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
652 switch ((*desc)->getTag())
654 case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
656 if (system != iDVBFrontend::feCable)
657 break; // when current locked transponder is no cable transponder ignore this descriptor
658 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
659 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
660 eDVBFrontendParametersCable cable;
662 feparm->setDVBC(cable);
664 unsigned long hash=0;
665 feparm->getHash(hash);
666 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
669 eDVBChannelID(ns, tsid, onid),
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 unsigned long hash=0;
684 feparm->getHash(hash);
685 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
688 eDVBChannelID(ns, tsid, onid),
692 case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
694 if (system != iDVBFrontend::feSatellite)
695 break; // when current locked transponder is no satellite transponder ignore this descriptor
697 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
698 if (d.getFrequency() < 10000)
701 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
702 eDVBFrontendParametersSatellite sat;
705 eDVBFrontendParametersSatellite p;
706 m_ch_current->getDVBS(p);
708 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
709 sat.orbital_position = p.orbital_position;
711 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
713 SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
714 sat.orbital_position = p.orbital_position;
717 feparm->setDVBS(sat);
719 if ( p.orbital_position != sat.orbital_position)
720 SCAN_eDebug("dropping this transponder, it's on another satellite.");
723 unsigned long hash=0;
724 feparm->getHash(hash);
726 eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
732 SCAN_eDebug("descr<%x>", (*desc)->getTag());
740 /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
741 no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
744 This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
746 if (m_flags & clearToScanOnFirstNIT)
748 if (m_ch_toScan.empty())
750 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
751 m_ch_toScan = m_ch_toScan_backup;
753 m_flags &= ~clearToScanOnFirstNIT;
755 m_ready &= ~validNIT;
758 if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
760 if (m_abort_current_pmt)
762 m_abort_current_pmt = false;
768 SCAN_eDebug("channel done!");
770 /* if we had services on this channel, we declare
771 this channels as "known good". add it.
773 (TODO: not yet implemented)
774 a NIT entry could have possible overridden
775 our frontend data with more exact data.
777 (TODO: not yet implemented)
778 the tuning process could have lead to more
779 exact data than the user entered.
781 The channel id was probably corrected
782 by the data written in the SDT. this is
783 important, as "initial transponder lists"
784 usually don't have valid CHIDs (and that's
787 These are the reasons for adding the transponder
788 here, and not before.
792 if (m_ch_current->getSystem(type))
795 for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
797 eServiceReferenceDVB ref;
798 ePtr<eDVBService> service = new eDVBService;
802 unsigned long hash = 0;
804 m_ch_current->getHash(hash);
806 m_chid_current = eDVBChannelID(
807 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
808 m_pat_tsid, eOriginalNetworkID(0));
811 if (m_pmt_in_progress->second.serviceType == 1)
812 SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
813 else if (m_pmt_in_progress->second.serviceType == 2)
814 SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
816 SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
818 ref.set(m_chid_current);
819 ref.setServiceID(m_pmt_in_progress->first);
820 ref.setServiceType(m_pmt_in_progress->second.serviceType);
826 memset(pname, 0, sizeof(pname));
827 memset(sname, 0, sizeof(sname));
830 case iDVBFrontend::feSatellite:
832 eDVBFrontendParametersSatellite parm;
833 m_ch_current->getDVBS(parm);
834 snprintf(sname, 255, "%d%c SID 0x%02x",
836 parm.polarisation ? 'V' : 'H',
837 m_pmt_in_progress->first);
838 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
839 parm.system ? "DVB-S2" : "DVB-S",
840 parm.modulation == 1 ? "QPSK" : "8PSK",
842 parm.polarisation ? 'V' : 'H',
843 parm.orbital_position/10,
844 parm.orbital_position%10,
845 parm.orbital_position > 0 ? 'E' : 'W');
848 case iDVBFrontend::feTerrestrial:
850 eDVBFrontendParametersTerrestrial parm;
851 m_ch_current->getDVBT(parm);
852 snprintf(sname, 255, "%d SID 0x%02x",
854 m_pmt_in_progress->first);
857 case iDVBFrontend::feCable:
859 eDVBFrontendParametersCable parm;
860 m_ch_current->getDVBC(parm);
861 snprintf(sname, 255, "%d SID 0x%02x",
863 m_pmt_in_progress->first);
867 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
868 service->m_service_name = convertDVBUTF8(sname);
869 service->genSortName();
870 service->m_provider_name = convertDVBUTF8(pname);
873 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
874 SCAN_eDebug("add not scrambled!");
875 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
876 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
879 m_last_service = i.first;
880 m_event(evtNewService);
884 SCAN_eDebug("dont add... is scrambled!");
885 m_pmts_to_read.erase(m_pmt_in_progress++);
889 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
892 addKnownGoodChannel(m_chid_current, m_ch_current);
897 case iDVBFrontend::feSatellite:
898 case iDVBFrontend::feTerrestrial:
899 case iDVBFrontend::feCable:
901 ePtr<iDVBFrontend> fe;
902 if (!m_channel->getFrontend(fe))
904 ePyObject tp_dict = PyDict_New();
905 fe->getTransponderData(tp_dict, false);
906 // eDebug("add tuner data for tsid %04x, onid %04x, ns %08x",
907 // m_chid_current.transport_stream_id.get(), m_chid_current.original_network_id.get(),
908 // m_chid_current.dvbnamespace.get());
909 m_tuner_data.insert(std::pair<eDVBChannelID, ePyObjectWrapper>(m_chid_current, tp_dict));
919 m_ch_scanned.push_back(m_ch_current);
921 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
923 if (sameChannel(*i, m_ch_current))
925 SCAN_eDebug("remove dupe 2");
926 m_ch_toScan.erase(i++);
935 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
939 m_ch_scanned.clear();
940 m_ch_unavailable.clear();
941 m_new_channels.clear();
942 m_tuner_data.clear();
943 m_new_services.clear();
944 m_last_service = m_new_services.end();
946 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
949 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
951 if (sameChannel(*i, *ii, true))
958 m_ch_toScan.push_back(*i);
964 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
966 if (m_flags & scanRemoveServices)
968 bool clearTerrestrial=false;
969 bool clearCable=false;
970 std::set<unsigned int> scanned_sat_positions;
972 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
973 for (;it != m_ch_scanned.end(); ++it)
975 if (m_flags & scanDontRemoveUnscanned)
976 db->removeServices(&(*(*it)));
980 (*it)->getSystem(system);
983 case iDVBFrontend::feSatellite:
985 eDVBFrontendParametersSatellite sat_parm;
986 (*it)->getDVBS(sat_parm);
987 scanned_sat_positions.insert(sat_parm.orbital_position);
990 case iDVBFrontend::feTerrestrial:
992 clearTerrestrial=true;
995 case iDVBFrontend::feCable:
1004 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
1006 if (m_flags & scanDontRemoveUnscanned)
1007 db->removeServices(&(*(*it)));
1011 (*it)->getSystem(system);
1014 case iDVBFrontend::feSatellite:
1016 eDVBFrontendParametersSatellite sat_parm;
1017 (*it)->getDVBS(sat_parm);
1018 scanned_sat_positions.insert(sat_parm.orbital_position);
1021 case iDVBFrontend::feTerrestrial:
1023 clearTerrestrial=true;
1026 case iDVBFrontend::feCable:
1035 if (clearTerrestrial)
1038 chid.dvbnamespace=0xEEEE0000;
1039 db->removeServices(chid);
1044 chid.dvbnamespace=0xFFFF0000;
1045 db->removeServices(chid);
1047 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
1050 if (m_flags & scanDontRemoveFeeds)
1051 chid.dvbnamespace = eDVBNamespace((*x)<<16);
1052 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
1053 db->removeServices(chid, *x);
1057 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
1058 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
1061 ch->second->getSystem(system);
1062 std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
1066 case iDVBFrontend::feTerrestrial:
1068 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
1069 eDVBFrontendParametersTerrestrial parm;
1070 int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
1072 // eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
1073 // ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
1074 // ch->first.dvbnamespace.get(), freq, parm.frequency);
1075 parm.frequency = freq;
1079 case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
1080 case iDVBFrontend::feCable:
1084 if (m_flags & scanOnlyFree)
1086 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
1087 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
1090 db->addChannelToList(ch->first, ch->second);
1093 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
1094 service(m_new_services.begin()); service != m_new_services.end(); ++service)
1096 ePtr<eDVBService> dvb_service;
1097 if (!db->getService(service->first, dvb_service))
1099 if (dvb_service->m_flags & eDVBService::dxNoSDT)
1101 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
1103 dvb_service->m_service_name = service->second->m_service_name;
1104 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
1106 dvb_service->m_provider_name = service->second->m_provider_name;
1107 if (service->second->m_ca.size())
1108 dvb_service->m_ca = service->second->m_ca;
1109 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
1110 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1114 db->addService(service->first, service->second);
1115 if (!(m_flags & scanRemoveServices))
1116 service->second->m_flags |= eDVBService::dxNewFound;
1121 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1123 const ServiceDescriptionList &services = *sdt.getDescriptions();
1124 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1125 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1127 /* save correct CHID for this channel */
1128 m_chid_current = chid;
1130 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1132 unsigned short service_id = (*s)->getServiceId();
1133 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1136 if (m_flags & scanOnlyFree)
1138 std::map<unsigned short, service>::iterator it =
1139 m_pmts_to_read.find(service_id);
1140 if (it != m_pmts_to_read.end())
1142 if (it->second.scrambled)
1144 SCAN_eDebug("is scrambled!");
1148 SCAN_eDebug("is free");
1151 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1158 eServiceReferenceDVB ref;
1159 ePtr<eDVBService> service = new eDVBService;
1162 ref.setServiceID(service_id);
1164 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1165 desc != (*s)->getDescriptors()->end(); ++desc)
1167 switch ((*desc)->getTag())
1169 case SERVICE_DESCRIPTOR:
1171 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1172 ref.setServiceType(d.getServiceType());
1173 service->m_service_name = convertDVBUTF8(d.getServiceName());
1174 service->genSortName();
1176 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1177 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1180 case CA_IDENTIFIER_DESCRIPTOR:
1182 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1183 const CaSystemIdList &caids = *d.getCaSystemIds();
1184 SCAN_eDebugNoNewLine("CA ");
1185 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1187 SCAN_eDebugNoNewLine("%04x ", *i);
1188 service->m_ca.push_front(*i);
1194 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1199 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1200 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1204 m_last_service = i.first;
1205 m_event(evtNewService);
1208 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1209 m_abort_current_pmt = true;
1211 m_pmts_to_read.erase(service_id);
1217 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1219 connection = new eConnection(this, m_event.connect(event));
1223 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1225 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1226 transponders_total = m_ch_toScan.size() + transponders_done;
1227 services = m_new_services.size();
1230 void eDVBScan::getLastServiceName(std::string &last_service_name)
1232 if (m_last_service == m_new_services.end())
1233 last_service_name = "";
1235 last_service_name = m_last_service->second->m_service_name;
1238 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1241 return m_channel->getFrontend(fe);
1246 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)