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>
17 #define SCAN_eDebug(x...) do { if (m_scan_debug) eDebug(x); } while(0)
18 #define SCAN_eDebugNoNewLine(x...) do { if (m_scan_debug) eDebugNoNewLine(x); } while(0)
22 eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug)
23 :m_channel(channel), m_channel_state(iDVBChannel::state_idle)
24 ,m_ready(0), m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT)
25 ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0)
26 ,m_usePAT(usePAT), m_scan_debug(debug)
28 if (m_channel->getDemux(m_demux))
29 SCAN_eDebug("scan: failed to allocate demux!");
30 m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
37 int eDVBScan::isValidONIDTSID(int orbital_position, eOriginalNetworkID onid, eTransportStreamID tsid)
44 case 0x13E: // workaround for 11258H and 11470V on hotbird with same ONID/TSID (0x13E/0x578)
45 return orbital_position != 130 || tsid != 0x578;
47 return orbital_position == 192;
49 return tsid != 0x00B0;
51 return tsid != 0x4321;
53 return abs(orbital_position-282) < 6;
55 return onid.get() < 0xFF00;
59 eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash)
61 // on valid ONIDs, ignore frequency ("sub network") part
62 if (isValidONIDTSID((hash >> 16) & 0xFFFF, onid, tsid))
64 return eDVBNamespace(hash);
67 void eDVBScan::stateChange(iDVBChannel *ch)
70 if (ch->getState(state))
72 if (m_channel_state == state)
75 if (state == iDVBChannel::state_ok)
78 m_channel_state = state;
79 } else if (state == iDVBChannel::state_failed)
81 m_ch_unavailable.push_back(m_ch_current);
84 /* unavailable will timeout, anyway. */
87 RESULT eDVBScan::nextChannel()
89 ePtr<iDVBFrontend> fe;
91 m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0;
95 m_pat_tsid = eTransportStreamID();
97 /* check what we need */
98 m_ready_all = readySDT;
100 if (m_flags & scanNetworkSearch)
101 m_ready_all |= readyNIT;
103 if (m_flags & scanSearchBAT)
104 m_ready_all |= readyBAT;
107 m_ready_all |= readyPAT;
109 if (m_ch_toScan.empty())
111 SCAN_eDebug("no channels left to scan.");
112 SCAN_eDebug("%d channels scanned, %d were unavailable.",
113 m_ch_scanned.size(), m_ch_unavailable.size());
114 SCAN_eDebug("%d channels in database.", m_new_channels.size());
119 m_ch_current = m_ch_toScan.front();
121 m_ch_toScan.pop_front();
123 if (m_channel->getFrontend(fe))
129 m_chid_current = eDVBChannelID();
131 m_channel_state = iDVBChannel::state_idle;
133 if (fe->tune(*m_ch_current))
134 return nextChannel();
140 RESULT eDVBScan::startFilter()
145 /* only start required filters filter */
147 if (m_ready_all & readyPAT)
148 startSDT = m_ready & readyPAT;
150 // m_ch_current is not set, when eDVBScan is just used for a SDT update
153 unsigned int channelFlags;
154 m_channel->getCurrentFrontendParameters(m_ch_current);
155 m_ch_current->getFlags(channelFlags);
156 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
157 m_flags |= scanOnlyFree;
161 if (startSDT && (m_ready_all & readySDT))
163 m_SDT = new eTable<ServiceDescriptionSection>(m_scan_debug);
165 if (m_ready & readyPAT && m_ready & validPAT)
167 std::vector<ProgramAssociationSection*>::const_iterator i =
168 m_PAT->getSections().begin();
169 ASSERT(i != m_PAT->getSections().end());
170 tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
171 m_pat_tsid = eTransportStreamID(tsid);
172 for (; i != m_PAT->getSections().end(); ++i)
174 const ProgramAssociationSection &pat = **i;
175 ProgramAssociationConstIterator program = pat.getPrograms()->begin();
176 for (; program != pat.getPrograms()->end(); ++program)
177 m_pmts_to_read.insert(std::pair<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
179 m_PMT = new eTable<ProgramMapSection>(m_scan_debug);
180 CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
182 // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
186 m_ch_current->getSystem(type);
187 if (type == iDVBFrontend::feCable)
189 eDVBFrontendParametersCable parm;
190 m_ch_current->getDVBC(parm);
191 if ((tsid == 0x00d7 && abs(parm.frequency-618000) < 2000) ||
192 (tsid == 0x00d8 && abs(parm.frequency-626000) < 2000))
199 if (m_SDT->start(m_demux, eDVBSDTSpec()))
202 else if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
204 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
207 if (!(m_ready & readyPAT))
210 if (m_ready_all & readyPAT)
212 m_PAT = new eTable<ProgramAssociationSection>(m_scan_debug);
213 if (m_PAT->start(m_demux, eDVBPATSpec(4000)))
215 CONNECT(m_PAT->tableReady, eDVBScan::PATready);
219 if (m_ready_all & readyNIT)
221 m_NIT = new eTable<NetworkInformationSection>(m_scan_debug);
222 if (m_NIT->start(m_demux, eDVBNITSpec()))
224 CONNECT(m_NIT->tableReady, eDVBScan::NITready);
228 if (m_ready_all & readyBAT)
230 m_BAT = new eTable<BouquetAssociationSection>(m_scan_debug);
231 if (m_BAT->start(m_demux, eDVBBATSpec()))
233 CONNECT(m_BAT->tableReady, eDVBScan::BATready);
239 void eDVBScan::SDTready(int err)
241 SCAN_eDebug("got sdt %d", err);
248 void eDVBScan::NITready(int err)
250 SCAN_eDebug("got nit, err %d", err);
257 void eDVBScan::BATready(int err)
259 SCAN_eDebug("got bat");
266 void eDVBScan::PATready(int err)
268 SCAN_eDebug("got pat");
272 startFilter(); // for starting the SDT filter
275 void eDVBScan::PMTready(int err)
277 SCAN_eDebug("got pmt %d", err);
280 bool scrambled = false;
281 bool have_audio = false;
282 bool have_video = false;
283 unsigned short pcrpid = 0xFFFF;
284 std::vector<ProgramMapSection*>::const_iterator i;
286 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
288 const ProgramMapSection &pmt = **i;
289 if (pcrpid == 0xFFFF)
290 pcrpid = pmt.getPcrPid();
292 SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
293 ElementaryStreamInfoConstIterator es;
294 for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
296 int isaudio = 0, isvideo = 0, is_scrambled = 0, forced_audio = 0, forced_video = 0;
297 switch ((*es)->getType())
299 case 0x1b: // AVC Video Stream (MPEG4 H264)
300 case 0x10: // MPEG 4 Part 2
301 case 0x01: // MPEG 1 video
302 case 0x02: // MPEG 2 video
305 //break; fall through !!!
306 case 0x03: // MPEG 1 audio
307 case 0x04: // MPEG 2 audio
308 case 0x0f: // MPEG 2 AAC
309 case 0x11: // MPEG 4 AAC
315 case 0x06: // PES Private
316 case 0x81: // user private
317 case 0xEA: // TS_PSI_ST_SMPTE_VC1
318 for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
319 desc != (*es)->getDescriptors()->end(); ++desc)
321 uint8_t tag = (*desc)->getTag();
322 /* PES private can contain AC-3, DTS or lots of other stuff.
323 check descriptors to get the exakt type. */
324 if (!forced_video && !forced_audio)
328 case 0x1C: // TS_PSI_DT_MPEG4_Audio
329 case 0x2B: // TS_PSI_DT_MPEG2_AAC
333 case AUDIO_STREAM_DESCRIPTOR:
336 case 0x28: // TS_PSI_DT_AVC
337 case 0x1B: // TS_PSI_DT_MPEG4_Video
338 case VIDEO_STREAM_DESCRIPTOR:
341 case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
343 RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc);
344 switch (d->getFormatIdentifier())
346 case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
347 case 0x41432d33: // == 'AC-3'
348 case 0x42535344: // == 'BSSD' (LPCM)
351 case 0x56432d31: // == 'VC-1'
362 if (tag == CA_DESCRIPTOR)
377 for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
378 desc != pmt.getDescriptors()->end(); ++desc)
380 if ((*desc)->getTag() == CA_DESCRIPTOR)
384 m_pmt_in_progress->second.scrambled = scrambled;
386 m_pmt_in_progress->second.serviceType = 1;
387 else if ( have_audio )
388 m_pmt_in_progress->second.serviceType = 2;
390 m_pmt_in_progress->second.serviceType = 100;
392 if (err == -1) // timeout or removed by sdt
393 m_pmts_to_read.erase(m_pmt_in_progress++);
394 else if (m_pmt_running)
398 m_pmt_in_progress = m_pmts_to_read.begin();
399 m_pmt_running = true;
402 if (m_pmt_in_progress != m_pmts_to_read.end())
403 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
407 m_pmt_running = false;
413 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
415 /* add it to the list of known channels. */
417 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
420 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
422 /* check if we don't already have that channel ... */
425 feparm->getSystem(type);
429 case iDVBFrontend::feSatellite:
431 eDVBFrontendParametersSatellite parm;
432 feparm->getDVBS(parm);
433 SCAN_eDebug("try to add %d %d %d %d %d %d",
434 parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
437 case iDVBFrontend::feCable:
439 eDVBFrontendParametersCable parm;
440 feparm->getDVBC(parm);
441 SCAN_eDebug("try to add %d %d %d %d",
442 parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
445 case iDVBFrontend::feTerrestrial:
447 eDVBFrontendParametersTerrestrial parm;
448 feparm->getDVBT(parm);
449 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
450 parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
451 parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
457 /* ... in the list of channels to scan */
458 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
460 if (sameChannel(*i, feparm))
464 *i = feparm; // update
465 SCAN_eDebug("update");
469 SCAN_eDebug("remove dupe");
470 m_ch_toScan.erase(i++);
480 SCAN_eDebug("already in todo list");
484 /* ... in the list of successfully scanned channels */
485 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
486 if (sameChannel(*i, feparm))
488 SCAN_eDebug("successfully scanned");
492 /* ... in the list of unavailable channels */
493 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
494 if (sameChannel(*i, feparm, true))
496 SCAN_eDebug("scanned but not available");
500 /* ... on the current channel */
501 if (sameChannel(m_ch_current, feparm))
503 SCAN_eDebug("is current");
507 SCAN_eDebug("really add");
508 /* otherwise, add it to the todo list. */
509 m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
512 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
515 if (ch1->calculateDifference(ch2, diff, exact))
517 if (diff < 4000) // more than 4mhz difference?
522 void eDVBScan::channelDone()
524 if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
526 unsigned long hash = 0;
528 m_ch_current->getHash(hash);
530 eDVBNamespace dvbnamespace = buildNamespace(
531 (**m_SDT->getSections().begin()).getOriginalNetworkId(),
532 (**m_SDT->getSections().begin()).getTransportStreamId(),
535 SCAN_eDebug("SDT: ");
536 std::vector<ServiceDescriptionSection*>::const_iterator i;
537 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
538 processSDT(dvbnamespace, **i);
539 m_ready &= ~validSDT;
542 if (m_ready & validNIT)
545 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
546 m_ch_current->getSystem(system);
547 SCAN_eDebug("dumping NIT");
548 if (m_flags & clearToScanOnFirstNIT)
550 m_ch_toScan_backup = m_ch_toScan;
553 std::vector<NetworkInformationSection*>::const_iterator i;
554 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
556 const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
558 for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin());
559 tsinfo != tsinfovec.end(); ++tsinfo)
561 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
562 (*tsinfo)->getOriginalNetworkId());
564 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
565 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
567 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
568 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
570 switch ((*desc)->getTag())
572 case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
574 if (system != iDVBFrontend::feCable)
575 break; // when current locked transponder is no cable transponder ignore this descriptor
576 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
577 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
578 eDVBFrontendParametersCable cable;
580 feparm->setDVBC(cable);
582 unsigned long hash=0;
583 feparm->getHash(hash);
584 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
587 eDVBChannelID(ns, tsid, onid),
591 case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
593 if (system != iDVBFrontend::feTerrestrial)
594 break; // when current locked transponder is no terrestrial transponder ignore this descriptor
595 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
596 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
597 eDVBFrontendParametersTerrestrial terr;
599 feparm->setDVBT(terr);
601 unsigned long hash=0;
602 feparm->getHash(hash);
603 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
606 eDVBChannelID(ns, tsid, onid),
610 case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
612 if (system != iDVBFrontend::feSatellite)
613 break; // when current locked transponder is no satellite transponder ignore this descriptor
615 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
616 if (d.getFrequency() < 10000)
619 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
620 eDVBFrontendParametersSatellite sat;
623 eDVBFrontendParametersSatellite p;
624 m_ch_current->getDVBS(p);
626 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
627 sat.orbital_position = p.orbital_position;
629 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
631 SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
632 sat.orbital_position = p.orbital_position;
635 feparm->setDVBS(sat);
637 if ( p.orbital_position != sat.orbital_position)
638 SCAN_eDebug("dropping this transponder, it's on another satellite.");
641 unsigned long hash=0;
642 feparm->getHash(hash);
644 eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
650 SCAN_eDebug("descr<%x>", (*desc)->getTag());
658 /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
659 no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
662 This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
664 if (m_flags & clearToScanOnFirstNIT)
666 if (m_ch_toScan.empty())
668 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
669 m_ch_toScan = m_ch_toScan_backup;
671 m_flags &= ~clearToScanOnFirstNIT;
673 m_ready &= ~validNIT;
676 if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
678 if (m_abort_current_pmt)
680 m_abort_current_pmt = false;
686 SCAN_eDebug("channel done!");
688 /* if we had services on this channel, we declare
689 this channels as "known good". add it.
691 (TODO: not yet implemented)
692 a NIT entry could have possible overridden
693 our frontend data with more exact data.
695 (TODO: not yet implemented)
696 the tuning process could have lead to more
697 exact data than the user entered.
699 The channel id was probably corrected
700 by the data written in the SDT. this is
701 important, as "initial transponder lists"
702 usually don't have valid CHIDs (and that's
705 These are the reasons for adding the transponder
706 here, and not before.
710 if (m_ch_current->getSystem(type))
713 for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
715 eServiceReferenceDVB ref;
716 ePtr<eDVBService> service = new eDVBService;
720 unsigned long hash = 0;
722 m_ch_current->getHash(hash);
724 m_chid_current = eDVBChannelID(
725 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
726 m_pat_tsid, eOriginalNetworkID(0));
729 if (m_pmt_in_progress->second.serviceType == 1)
730 SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
731 else if (m_pmt_in_progress->second.serviceType == 2)
732 SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
734 SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
736 ref.set(m_chid_current);
737 ref.setServiceID(m_pmt_in_progress->first);
738 ref.setServiceType(m_pmt_in_progress->second.serviceType);
744 memset(pname, 0, sizeof(pname));
745 memset(sname, 0, sizeof(sname));
748 case iDVBFrontend::feSatellite:
750 eDVBFrontendParametersSatellite parm;
751 m_ch_current->getDVBS(parm);
752 snprintf(sname, 255, "%d%c SID 0x%02x",
754 parm.polarisation ? 'V' : 'H',
755 m_pmt_in_progress->first);
756 snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
757 parm.system ? "DVB-S2" : "DVB-S",
758 parm.modulation == 1 ? "QPSK" : "8PSK",
760 parm.polarisation ? 'V' : 'H',
761 parm.orbital_position/10,
762 parm.orbital_position%10,
763 parm.orbital_position > 0 ? 'E' : 'W');
766 case iDVBFrontend::feTerrestrial:
768 eDVBFrontendParametersTerrestrial parm;
769 m_ch_current->getDVBT(parm);
770 snprintf(sname, 255, "%d SID 0x%02x",
772 m_pmt_in_progress->first);
775 case iDVBFrontend::feCable:
777 eDVBFrontendParametersCable parm;
778 m_ch_current->getDVBC(parm);
779 snprintf(sname, 255, "%d SID 0x%02x",
781 m_pmt_in_progress->first);
785 SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
786 service->m_service_name = convertDVBUTF8(sname);
787 service->genSortName();
788 service->m_provider_name = convertDVBUTF8(pname);
791 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
792 SCAN_eDebug("add not scrambled!");
793 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
794 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
797 m_last_service = i.first;
798 m_event(evtNewService);
802 SCAN_eDebug("dont add... is scrambled!");
803 m_pmts_to_read.erase(m_pmt_in_progress++);
807 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
810 addKnownGoodChannel(m_chid_current, m_ch_current);
815 case iDVBFrontend::feSatellite:
816 case iDVBFrontend::feTerrestrial:
817 case iDVBFrontend::feCable:
819 ePtr<iDVBFrontend> fe;
820 if (!m_channel->getFrontend(fe))
822 ePyObject tp_dict = PyDict_New();
823 fe->getTransponderData(tp_dict, false);
824 // eDebug("add tuner data for tsid %04x, onid %04x, ns %08x",
825 // m_chid_current.transport_stream_id.get(), m_chid_current.original_network_id.get(),
826 // m_chid_current.dvbnamespace.get());
827 m_tuner_data.insert(std::pair<eDVBChannelID, ePyObjectWrapper>(m_chid_current, tp_dict));
837 m_ch_scanned.push_back(m_ch_current);
839 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
841 if (sameChannel(*i, m_ch_current))
843 SCAN_eDebug("remove dupe 2");
844 m_ch_toScan.erase(i++);
853 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
857 m_ch_scanned.clear();
858 m_ch_unavailable.clear();
859 m_new_channels.clear();
860 m_tuner_data.clear();
861 m_new_services.clear();
862 m_last_service = m_new_services.end();
864 for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
867 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
869 if (sameChannel(*i, *ii, true))
876 m_ch_toScan.push_back(*i);
882 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
884 if (m_flags & scanRemoveServices)
886 bool clearTerrestrial=false;
887 bool clearCable=false;
888 std::set<unsigned int> scanned_sat_positions;
890 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
891 for (;it != m_ch_scanned.end(); ++it)
893 if (m_flags & scanDontRemoveUnscanned)
894 db->removeServices(&(*(*it)));
898 (*it)->getSystem(system);
901 case iDVBFrontend::feSatellite:
903 eDVBFrontendParametersSatellite sat_parm;
904 (*it)->getDVBS(sat_parm);
905 scanned_sat_positions.insert(sat_parm.orbital_position);
908 case iDVBFrontend::feTerrestrial:
910 clearTerrestrial=true;
913 case iDVBFrontend::feCable:
922 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
924 if (m_flags & scanDontRemoveUnscanned)
925 db->removeServices(&(*(*it)));
929 (*it)->getSystem(system);
932 case iDVBFrontend::feSatellite:
934 eDVBFrontendParametersSatellite sat_parm;
935 (*it)->getDVBS(sat_parm);
936 scanned_sat_positions.insert(sat_parm.orbital_position);
939 case iDVBFrontend::feTerrestrial:
941 clearTerrestrial=true;
944 case iDVBFrontend::feCable:
953 if (clearTerrestrial)
956 chid.dvbnamespace=0xEEEE0000;
957 db->removeServices(chid);
962 chid.dvbnamespace=0xFFFF0000;
963 db->removeServices(chid);
965 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
968 if (m_flags & scanDontRemoveFeeds)
969 chid.dvbnamespace = eDVBNamespace((*x)<<16);
970 // eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
971 db->removeServices(chid, *x);
975 for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
976 ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
979 ch->second->getSystem(system);
980 std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
984 case iDVBFrontend::feTerrestrial:
986 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
987 eDVBFrontendParametersTerrestrial parm;
988 int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
990 // eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
991 // ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
992 // ch->first.dvbnamespace.get(), freq, parm.frequency);
993 parm.frequency = freq;
997 case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
998 case iDVBFrontend::feCable:
1002 if (m_flags & scanOnlyFree)
1004 eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
1005 ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
1008 db->addChannelToList(ch->first, ch->second);
1011 for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
1012 service(m_new_services.begin()); service != m_new_services.end(); ++service)
1014 ePtr<eDVBService> dvb_service;
1015 if (!db->getService(service->first, dvb_service))
1017 if (dvb_service->m_flags & eDVBService::dxNoSDT)
1019 if (!(dvb_service->m_flags & eDVBService::dxHoldName))
1021 dvb_service->m_service_name = service->second->m_service_name;
1022 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
1024 dvb_service->m_provider_name = service->second->m_provider_name;
1025 if (service->second->m_ca.size())
1026 dvb_service->m_ca = service->second->m_ca;
1027 if (!dontRemoveOldFlags) // do not remove new found flags when not wished
1028 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1032 db->addService(service->first, service->second);
1033 if (!(m_flags & scanRemoveServices))
1034 service->second->m_flags |= eDVBService::dxNewFound;
1039 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1041 const ServiceDescriptionList &services = *sdt.getDescriptions();
1042 SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1043 eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1045 /* save correct CHID for this channel */
1046 m_chid_current = chid;
1048 for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1050 unsigned short service_id = (*s)->getServiceId();
1051 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1054 if (m_flags & scanOnlyFree)
1056 std::map<unsigned short, service>::iterator it =
1057 m_pmts_to_read.find(service_id);
1058 if (it != m_pmts_to_read.end())
1060 if (it->second.scrambled)
1062 SCAN_eDebug("is scrambled!");
1066 SCAN_eDebug("is free");
1069 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1076 eServiceReferenceDVB ref;
1077 ePtr<eDVBService> service = new eDVBService;
1080 ref.setServiceID(service_id);
1082 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1083 desc != (*s)->getDescriptors()->end(); ++desc)
1085 switch ((*desc)->getTag())
1087 case SERVICE_DESCRIPTOR:
1089 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1090 ref.setServiceType(d.getServiceType());
1091 service->m_service_name = convertDVBUTF8(d.getServiceName());
1092 service->genSortName();
1094 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1095 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1098 case CA_IDENTIFIER_DESCRIPTOR:
1100 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1101 const CaSystemIdList &caids = *d.getCaSystemIds();
1102 SCAN_eDebugNoNewLine("CA ");
1103 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1105 SCAN_eDebugNoNewLine("%04x ", *i);
1106 service->m_ca.push_front(*i);
1112 SCAN_eDebug("descr<%x>", (*desc)->getTag());
1117 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1118 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1122 m_last_service = i.first;
1123 m_event(evtNewService);
1126 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1127 m_abort_current_pmt = true;
1129 m_pmts_to_read.erase(service_id);
1135 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1137 connection = new eConnection(this, m_event.connect(event));
1141 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1143 transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1144 transponders_total = m_ch_toScan.size() + transponders_done;
1145 services = m_new_services.size();
1148 void eDVBScan::getLastServiceName(std::string &last_service_name)
1150 if (m_last_service == m_new_services.end())
1151 last_service_name = "";
1153 last_service_name = m_last_service->second->m_service_name;
1156 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1159 return m_channel->getFrontend(fe);
1164 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)