Support DVB-S2X.
[vuplus_dvbapp] / lib / dvb / scan.cpp
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>
20 #include <errno.h>
21
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)
24
25 DEFINE_REF(eDVBScan);
26
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)
32 {
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");
38         if (f)
39         {
40                 char code[16384];
41                 size_t rd = fread(code, 1, 16383, f);
42                 if (rd)
43                 {
44                         code[rd]=0;
45                         m_additional_tsid_onid_check_func = Py_CompileString(code, filename.c_str(), Py_file_input);
46                 }
47                 fclose(f);
48         }
49 }
50
51 eDVBScan::~eDVBScan()
52 {
53         if (m_additional_tsid_onid_check_func)
54                 Py_DECREF(m_additional_tsid_onid_check_func);
55 }
56
57 int eDVBScan::isValidONIDTSID(int orbital_position, eOriginalNetworkID onid, eTransportStreamID tsid)
58 {
59         int ret;
60         switch (onid.get())
61         {
62         case 0:
63         case 0x1111:
64                 ret=0;
65                 break;
66         case 0x13E:  // workaround for 11258H and 11470V on hotbird with same ONID/TSID (0x13E/0x578)
67                 ret = orbital_position != 130 || tsid != 0x578;
68                 break;
69         case 1:
70                 ret = orbital_position == 192;
71                 break;
72         case 0x00B1:
73                 ret = tsid != 0x00B0;
74                 break;
75         case 0x00eb:
76                 ret = tsid != 0x4321;
77                 break;
78         case 0x0002:
79                 ret = abs(orbital_position-282) < 6 && tsid != 2019;
80                 // 12070H and 10936V have same tsid/onid.. but even the same services are provided
81                 break;
82         case 0x2000:
83                 ret = tsid != 0x1000;
84                 break;
85         case 0x5E: // Sirius 4.8E 12322V and 12226H
86                 ret = abs(orbital_position-48) < 3 && tsid != 1;
87                 break;
88         case 10100: // Eutelsat W7 36.0E 11644V and 11652V
89                 ret = orbital_position != 360 || tsid != 10187;
90                 break;
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
97                 break;
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;
100                 break;
101         case 70: // Thor 0.8W 11862H 12341V
102                 ret = abs(orbital_position-3592) < 3 && tsid != 46;
103                 break;
104         case 32: // NSS 806 (40.5W) 4059R, 3774L
105                 ret = orbital_position != 3195 || tsid != 21;
106                 break;
107         default:
108                 ret = onid.get() < 0xFF00;
109                 break;
110         }
111         if (ret && m_additional_tsid_onid_check_func)
112         {
113                 bool failed = true;
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);
121                 if (r)
122                 {
123                         ePyObject o = PyDict_GetItemString(dict, "ret");
124                         if (o)
125                         {
126                                 if (PyInt_Check(o))
127                                 {
128                                         ret = PyInt_AsLong(o);
129                                         failed = false;
130                                 }
131                         }
132                         Py_DECREF(r);
133                 }
134                 if (failed && m_show_add_tsid_onid_check_failed_msg)
135                 {
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;
140                 }
141                 Py_DECREF(dict);
142         }
143         return ret;
144 }
145
146 eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash)
147 {
148                 // on valid ONIDs, ignore frequency ("sub network") part
149         if (isValidONIDTSID((hash >> 16) & 0xFFFF, onid, tsid))
150                 hash &= ~0xFFFF;
151         return eDVBNamespace(hash);
152 }
153
154 void eDVBScan::stateChange(iDVBChannel *ch)
155 {
156         int state;
157         if (ch->getState(state))
158                 return;
159         if (m_channel_state == state)
160                 return;
161         
162         if (state == iDVBChannel::state_ok)
163         {
164                 startFilter();
165                 m_channel_state = state;
166         } else if (state == iDVBChannel::state_failed)
167         {
168                 m_ch_unavailable.push_back(m_ch_current);
169                 nextChannel();
170         }
171                         /* unavailable will timeout, anyway. */
172 }
173
174 RESULT eDVBScan::nextChannel()
175 {
176         ePtr<iDVBFrontend> fe;
177
178         m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0;
179
180         m_ready = 0;
181
182         m_pat_tsid = eTransportStreamID();
183
184                 /* check what we need */
185         m_ready_all = readySDT;
186         
187         if (m_flags & scanNetworkSearch)
188                 m_ready_all |= readyNIT;
189         
190         if (m_flags & scanSearchBAT)
191                 m_ready_all |= readyBAT;
192
193         if (m_usePAT)
194                 m_ready_all |= readyPAT;
195
196         if (m_ch_toScan.empty())
197         {
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());
202                 m_event(evtFinish);
203                 return -ENOENT;
204         }
205         
206         m_ch_current = m_ch_toScan.front();
207         
208         m_ch_toScan.pop_front();
209         
210         if (m_channel->getFrontend(fe))
211         {
212                 m_event(evtFail);
213                 return -ENOTSUP;
214         }
215
216         m_chid_current = eDVBChannelID();
217
218         m_channel_state = iDVBChannel::state_idle;
219
220         if (fe->tune(*m_ch_current))
221                 return nextChannel();
222
223         m_event(evtUpdate);
224         return 0;
225 }
226
227 RESULT eDVBScan::startFilter()
228 {
229         bool startSDT=true;
230         ASSERT(m_demux);
231
232                         /* only start required filters filter */
233
234         if (m_ready_all & readyPAT)
235                 startSDT = m_ready & readyPAT;
236
237         // m_ch_current is not set, when eDVBScan is just used for a SDT update
238         if (!m_ch_current)
239         {
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;
245         }
246
247         m_SDT = 0;
248         if (startSDT && (m_ready_all & readySDT))
249         {
250                 m_SDT = new eTable<ServiceDescriptionSection>(m_scan_debug);
251                 int tsid=-1;
252                 if (m_ready & readyPAT && m_ready & validPAT)
253                 {
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)
260                         {
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())));
265                         }
266                         m_PMT = new eTable<ProgramMapSection>(m_scan_debug);
267                         CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
268                         PMTready(-2);
269                         // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
270
271                         {
272                                 int type;
273                                 m_ch_current->getSystem(type);
274                                 if (type == iDVBFrontend::feCable)
275                                 {
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))
280                                                 tsid = -1;
281                                 }
282                         }
283                 }
284                 if (tsid == -1)
285                 {
286                         if (m_SDT->start(m_demux, eDVBSDTSpec()))
287                                 return -1;
288                 }
289                 else if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
290                         return -1;
291                 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
292         }
293
294         if (!(m_ready & readyPAT))
295         {
296                 m_PAT = 0;
297                 if (m_ready_all & readyPAT)
298                 {
299                         m_PAT = new eTable<ProgramAssociationSection>(m_scan_debug);
300                         if (m_PAT->start(m_demux, eDVBPATSpec(4000)))
301                                 return -1;
302                         CONNECT(m_PAT->tableReady, eDVBScan::PATready);
303                 }
304
305                 m_NIT = 0;
306                 if (m_ready_all & readyNIT)
307                 {
308                         m_NIT = new eTable<NetworkInformationSection>(m_scan_debug);
309                         if (m_NIT->start(m_demux, eDVBNITSpec()))
310                                 return -1;
311                         CONNECT(m_NIT->tableReady, eDVBScan::NITready);
312                 }
313
314                 m_BAT = 0;
315                 if (m_ready_all & readyBAT)
316                 {
317                         m_BAT = new eTable<BouquetAssociationSection>(m_scan_debug);
318                         if (m_BAT->start(m_demux, eDVBBATSpec()))
319                                 return -1;
320                         CONNECT(m_BAT->tableReady, eDVBScan::BATready);
321                 }
322         }
323         return 0;
324 }
325
326 void eDVBScan::SDTready(int err)
327 {
328         SCAN_eDebug("got sdt %d", err);
329         m_ready |= readySDT;
330         if (!err)
331                 m_ready |= validSDT;
332         channelDone();
333 }
334
335 void eDVBScan::NITready(int err)
336 {
337         SCAN_eDebug("got nit, err %d", err);
338         m_ready |= readyNIT;
339         if (!err)
340                 m_ready |= validNIT;
341         channelDone();
342 }
343
344 void eDVBScan::BATready(int err)
345 {
346         SCAN_eDebug("got bat");
347         m_ready |= readyBAT;
348         if (!err)
349                 m_ready |= validBAT;
350         channelDone();
351 }
352
353 void eDVBScan::PATready(int err)
354 {
355         SCAN_eDebug("got pat");
356         m_ready |= readyPAT;
357         if (!err)
358                 m_ready |= validPAT;
359         startFilter(); // for starting the SDT filter
360 }
361
362 void eDVBScan::PMTready(int err)
363 {
364         SCAN_eDebug("got pmt %d", err);
365         if (!err)
366         {
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;
372
373                 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
374                 {
375                         const ProgramMapSection &pmt = **i;
376                         if (pcrpid == 0xFFFF)
377                                 pcrpid = pmt.getPcrPid();
378                         else
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)
382                         {
383                                 int isaudio = 0, isvideo = 0, is_scrambled = 0, forced_audio = 0, forced_video = 0;
384                                 switch ((*es)->getType())
385                                 {
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
391                                         isvideo = 1;
392                                         forced_video = 1;
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
398                                         if (!isvideo) 
399                                         {
400                                                 forced_audio = 1;
401                                                 isaudio = 1;
402                                         }
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)
408                                         {
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)
413                                                 {
414                                                         switch (tag)
415                                                         {
416                                                         case 0x1C: // TS_PSI_DT_MPEG4_Audio
417                                                         case 0x2B: // TS_PSI_DT_MPEG2_AAC
418                                                         case AAC_DESCRIPTOR:
419                                                         case AC3_DESCRIPTOR:
420                                                         case DTS_DESCRIPTOR:
421                                                         case AUDIO_STREAM_DESCRIPTOR:
422                                                                 isaudio = 1;
423                                                                 break;
424                                                         case 0x28: // TS_PSI_DT_AVC
425                                                         case 0x1B: // TS_PSI_DT_MPEG4_Video
426                                                         case VIDEO_STREAM_DESCRIPTOR:
427                                                                 isvideo = 1;
428                                                                 break;
429                                                         case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
430                                                         {
431                                                                 RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc);
432                                                                 switch (d->getFormatIdentifier())
433                                                                 {
434                                                                 case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
435                                                                 case 0x41432d33: // == 'AC-3'
436                                                                 case 0x42535344: // == 'BSSD' (LPCM)
437                                                                         isaudio = 1;
438                                                                         break;
439                                                                 case 0x56432d31: // == 'VC-1'
440                                                                         isvideo = 1;
441                                                                         break;
442                                                                 default:
443                                                                         break;
444                                                                 }
445                                                         }
446                                                         default:
447                                                                 break;
448                                                         }
449                                                 }
450                                                 if (tag == CA_DESCRIPTOR)
451                                                         is_scrambled = 1;
452                                         }
453                                 default:
454                                         break;
455                                 }
456                                 if (isvideo)
457                                         have_video = true;
458                                 else if (isaudio)
459                                         have_audio = true;
460                                 else
461                                         continue;
462                                 if (is_scrambled)
463                                         scrambled = true;
464                         }
465                         for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
466                                 desc != pmt.getDescriptors()->end(); ++desc)
467                         {
468                                 if ((*desc)->getTag() == CA_DESCRIPTOR)
469                                         scrambled = true;
470                         }
471                 }
472                 m_pmt_in_progress->second.scrambled = scrambled;
473                 if ( have_video )
474                         m_pmt_in_progress->second.serviceType = 1;
475                 else if ( have_audio )
476                         m_pmt_in_progress->second.serviceType = 2;
477                 else
478                         m_pmt_in_progress->second.serviceType = 100;
479         }
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)
483                 ++m_pmt_in_progress;
484         else
485         {
486                 m_pmt_in_progress = m_pmts_to_read.begin();
487                 m_pmt_running = true;
488         }
489
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));
492         else
493         {
494                 m_PMT = 0;
495                 m_pmt_running = false;
496                 channelDone();
497         }
498 }
499
500
501 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
502 {
503                 /* add it to the list of known channels. */
504         if (chid)
505                 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
506 }
507
508 void eDVBScan::addChannelToScan(iDVBFrontendParameters *feparm)
509 {
510                 /* check if we don't already have that channel ... */
511
512         int type;
513         feparm->getSystem(type);
514
515         switch(type)
516         {
517         case iDVBFrontend::feSatellite:
518         {
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);
523                 break;
524         }
525         case iDVBFrontend::feCable:
526         {
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);
531                 break;
532         }
533         case iDVBFrontend::feTerrestrial:
534         {
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);
540                 break;
541         }
542         }
543
544         int found_count=0;
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();)
547         {
548                 if (sameChannel(*i, feparm))
549                 {
550                         if (!found_count)
551                         {
552                                 *i = feparm;  // update
553                                 SCAN_eDebug("update");
554                         }
555                         else
556                         {
557                                 SCAN_eDebug("remove dupe");
558                                 m_ch_toScan.erase(i++);
559                                 continue;
560                         }
561                         ++found_count;
562                 }
563                 ++i;
564         }
565
566         if (found_count > 0)
567         {
568                 SCAN_eDebug("already in todo list");
569                 return;
570         }
571
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))
575                 {
576                         SCAN_eDebug("successfully scanned");
577                         return;
578                 }
579
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))
583                 {
584                         SCAN_eDebug("scanned but not available");
585                         return;
586                 }
587
588                 /* ... on the current channel */
589         if (sameChannel(m_ch_current, feparm))
590         {
591                 SCAN_eDebug("is current");
592                 return;
593         }
594
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 :)
598 }
599
600 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
601 {
602         int diff;
603         if (ch1->calculateDifference(ch2, diff, exact))
604                 return 0;
605         if (diff < 4000) // more than 4mhz difference?
606                 return 1;
607         return 0;
608 }
609
610 void eDVBScan::channelDone()
611 {
612         if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
613         {
614                 unsigned long hash = 0;
615
616                 m_ch_current->getHash(hash);
617                 
618                 eDVBNamespace dvbnamespace = buildNamespace(
619                         (**m_SDT->getSections().begin()).getOriginalNetworkId(),
620                         (**m_SDT->getSections().begin()).getTransportStreamId(),
621                         hash);
622                 
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;
628         }
629         
630         if (m_ready & validNIT)
631         {
632                 int system;
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)
637                 {
638                         m_ch_toScan_backup = m_ch_toScan;
639                         m_ch_toScan.clear();
640                 }
641                 std::vector<NetworkInformationSection*>::const_iterator i;
642                 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
643                 {
644                         const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
645                         
646                         for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin()); 
647                                 tsinfo != tsinfovec.end(); ++tsinfo)
648                         {
649                                 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
650                                         (*tsinfo)->getOriginalNetworkId());
651
652                                 bool T2 = false;
653                                 eDVBFrontendParametersTerrestrial t2transponder;
654                                 
655                                 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
656                                                 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
657                                 {
658                                         switch ((*desc)->getTag())
659                                         {
660                                         case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
661                                         {
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;
667                                                 cable.set(d);
668                                                 feparm->setDVBC(cable);
669
670                                                 addChannelToScan(feparm);
671                                                 break;
672                                         }
673                                         case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
674                                         {
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;
680                                                 terr.set(d);
681                                                 feparm->setDVBT(terr);
682
683                                                 addChannelToScan(feparm);
684                                                 break;
685                                         }
686                                         case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
687                                         {
688                                                 if (system != iDVBFrontend::feSatellite)
689                                                         break; // when current locked transponder is no satellite transponder ignore this descriptor
690
691                                                 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
692                                                 if (d.getFrequency() < 10000)
693                                                         break;
694                                                 
695                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
696                                                 eDVBFrontendParametersSatellite sat;
697                                                 sat.set(d);
698
699                                                 eDVBFrontendParametersSatellite p;
700                                                 m_ch_current->getDVBS(p);
701
702                                                 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
703                                                         sat.orbital_position = p.orbital_position;
704
705                                                 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
706                                                 {
707                                                         SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
708                                                         sat.orbital_position = p.orbital_position;
709                                                 }
710
711                                                 feparm->setDVBS(sat);
712
713                                                 if ( p.orbital_position != sat.orbital_position)
714                                                         SCAN_eDebug("dropping this transponder, it's on another satellite.");
715                                                 else
716                                                 {
717                                                         addChannelToScan(feparm);
718                                                 }
719                                                 break;
720                                         }
721                                         case EXTENSION_DESCRIPTOR:
722                                         {
723                                                 if (system != iDVBFrontend::feTerrestrial)
724                                                         break; // when current locked transponder is no terrestrial transponder ignore this descriptor
725
726                                                 ExtensionDescriptor &d = (ExtensionDescriptor&)**desc;
727                                                 switch (d.getExtensionTag())
728                                                 {
729                                                 case T2_DELIVERY_SYSTEM_DESCRIPTOR:
730                                                         T2 = true;
731                                                         T2DeliverySystemDescriptor &d = (T2DeliverySystemDescriptor&)**desc;
732                                                         t2transponder.set(d);
733
734                                                         for (T2CellConstIterator cell = d.getCells()->begin();
735                                                                 cell != d.getCells()->end(); ++cell)
736                                                         {
737                                                                 for (T2FrequencyConstIterator freq = (*cell)->getCentreFrequencies()->begin();
738                                                                         freq != (*cell)->getCentreFrequencies()->end(); ++freq)
739                                                                 {
740                                                                         t2transponder.frequency = (*freq) * 10;
741                                                                         ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
742                                                                         feparm->setDVBT(t2transponder);
743                                                                         addChannelToScan(feparm);
744                                                                 }
745                                                         }
746                                                 }
747                                                 break;
748                                         }
749                                         case FREQUENCY_LIST_DESCRIPTOR:
750                                         {
751                                                 if (system != iDVBFrontend::feTerrestrial)
752                                                         break; // when current locked transponder is no terrestrial transponder ignore this descriptor
753                                                 if (!T2)
754                                                         break;
755
756                                                 FrequencyListDescriptor &d = (FrequencyListDescriptor&)**desc;
757                                                 if (d.getCodingType() != 0x03)
758                                                         break;
759
760                                                 for (CentreFrequencyConstIterator it = d.getCentreFrequencies()->begin();
761                                                                 it != d.getCentreFrequencies()->end(); ++it)
762                                                 {
763                                                         t2transponder.frequency = (*it) * 10;
764                                                         ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
765                                                         feparm->setDVBT(t2transponder);
766                                                         addChannelToScan(feparm);
767                                                 }
768                                                 break;
769                                         }
770                                         default:
771                                                 SCAN_eDebug("descr<%x>", (*desc)->getTag());
772                                                 break;
773                                         }
774                                 }
775                         }
776                         
777                 }
778
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
781                            has been found.
782
783                            This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
784                         */
785                 if (m_flags & clearToScanOnFirstNIT)
786                 {
787                         if (m_ch_toScan.empty())
788                         {
789                                 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
790                                 m_ch_toScan = m_ch_toScan_backup;
791                         } else
792                                 m_flags &= ~clearToScanOnFirstNIT;
793                 }
794                 m_ready &= ~validNIT;
795         }
796
797         if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
798         {
799                 if (m_abort_current_pmt)
800                 {
801                         m_abort_current_pmt = false;
802                         PMTready(-1);
803                 }
804                 return;
805         }
806
807         SCAN_eDebug("channel done!");
808         
809                 /* if we had services on this channel, we declare
810                    this channels as "known good". add it.
811                    
812                    (TODO: not yet implemented)
813                    a NIT entry could have possible overridden
814                    our frontend data with more exact data.
815                    
816                    (TODO: not yet implemented)
817                    the tuning process could have lead to more
818                    exact data than the user entered.
819                    
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
824                    good).
825                    
826                    These are the reasons for adding the transponder
827                    here, and not before.
828                 */
829
830         int type;
831         if (m_ch_current->getSystem(type))
832                 type = -1;
833
834         for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
835         {
836                 eServiceReferenceDVB ref;
837                 ePtr<eDVBService> service = new eDVBService;
838
839                 if (!m_chid_current)
840                 {
841                         unsigned long hash = 0;
842
843                         m_ch_current->getHash(hash);
844
845                         m_chid_current = eDVBChannelID(
846                                 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
847                                 m_pat_tsid, eOriginalNetworkID(0));
848                 }
849
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);
854                 else
855                         SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
856
857                 ref.set(m_chid_current);
858                 ref.setServiceID(m_pmt_in_progress->first);
859                 ref.setServiceType(m_pmt_in_progress->second.serviceType);
860
861                 if (type != -1)
862                 {
863                         char sname[255];
864                         char pname[255];
865                         memset(pname, 0, sizeof(pname));
866                         memset(sname, 0, sizeof(sname));
867                         switch(type)
868                         {
869                                 case iDVBFrontend::feSatellite:
870                                 {
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));
875
876                                         eDVBFrontendParametersSatellite parm;
877                                         m_ch_current->getDVBS(parm);
878
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");
883                                         else
884                                                 strcpy(system_name, "DVB-S");
885
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");
896                                         else
897                                                 strcpy(modulation_name, "8PSK");
898
899                                         snprintf(sname, 255, "%d%c SID 0x%02x",
900                                                         parm.frequency/1000,
901                                                         parm.polarisation ? 'V' : 'H',
902                                                         m_pmt_in_progress->first);
903                                         snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
904                                                 system_name,
905                                                 modulation_name,
906                                                 parm.frequency/1000,
907                                                 parm.polarisation ? 'V' : 'H',
908                                                 parm.orbital_position/10,
909                                                 parm.orbital_position%10,
910                                                 parm.orbital_position > 0 ? 'E' : 'W');
911                                         break;
912                                 }
913                                 case iDVBFrontend::feTerrestrial:
914                                 {
915                                         eDVBFrontendParametersTerrestrial parm;
916                                         m_ch_current->getDVBT(parm);
917                                         snprintf(sname, 255, "%d SID 0x%02x",
918                                                 parm.frequency/1000,
919                                                 m_pmt_in_progress->first);
920                                         break;
921                                 }
922                                 case iDVBFrontend::feCable:
923                                 {
924                                         eDVBFrontendParametersCable parm;
925                                         m_ch_current->getDVBC(parm);
926                                         snprintf(sname, 255, "%d SID 0x%02x",
927                                                 parm.frequency/1000,
928                                                 m_pmt_in_progress->first);
929                                         break;
930                                 }
931                         }
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);
936                 }
937
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));
942                         if (i.second)
943                         {
944                                 m_last_service = i.first;
945                                 m_event(evtNewService);
946                         }
947                 }
948                 else
949                         SCAN_eDebug("dont add... is scrambled!");
950                 m_pmts_to_read.erase(m_pmt_in_progress++);
951         }
952
953         if (!m_chid_current)
954                 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
955         else
956         {
957                 addKnownGoodChannel(m_chid_current, m_ch_current);
958                 if (m_chid_current)
959                 {
960                         switch(type)
961                         {
962                                 case iDVBFrontend::feSatellite:
963                                 case iDVBFrontend::feTerrestrial:
964                                 case iDVBFrontend::feCable:
965                                 {
966                                         ePtr<iDVBFrontend> fe;
967                                         if (!m_channel->getFrontend(fe))
968                                         {
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));
975                                                 Py_DECREF(tp_dict);
976                                         }
977                                 }
978                                 default:
979                                         break;
980                         }
981                 }
982         }
983
984         m_ch_scanned.push_back(m_ch_current);
985
986         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
987         {
988                 if (sameChannel(*i, m_ch_current))
989                 {
990                         SCAN_eDebug("remove dupe 2");
991                         m_ch_toScan.erase(i++);
992                         continue;
993                 }
994                 ++i;
995         }
996         
997         nextChannel();
998 }
999
1000 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
1001 {
1002         m_flags = 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();
1010
1011         for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
1012         {
1013                 bool exist=false;
1014                 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
1015                 {
1016                         if (sameChannel(*i, *ii, true))
1017                         {
1018                                 exist=true;
1019                                 break;
1020                         }
1021                 }
1022                 if (!exist)
1023                         m_ch_toScan.push_back(*i);
1024         }
1025
1026         nextChannel();
1027 }
1028
1029 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
1030 {
1031         if (m_flags & scanRemoveServices)
1032         {
1033                 bool clearTerrestrial=false;
1034                 bool clearCable=false;
1035                 std::set<unsigned int> scanned_sat_positions;
1036                 
1037                 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
1038                 for (;it != m_ch_scanned.end(); ++it)
1039                 {
1040                         if (m_flags & scanDontRemoveUnscanned)
1041                                 db->removeServices(&(*(*it)));
1042                         else
1043                         {
1044                                 int system;
1045                                 (*it)->getSystem(system);
1046                                 switch(system)
1047                                 {
1048                                         case iDVBFrontend::feSatellite:
1049                                         {
1050                                                 eDVBFrontendParametersSatellite sat_parm;
1051                                                 (*it)->getDVBS(sat_parm);
1052                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
1053                                                 break;
1054                                         }
1055                                         case iDVBFrontend::feTerrestrial:
1056                                         {
1057                                                 clearTerrestrial=true;
1058                                                 break;
1059                                         }
1060                                         case iDVBFrontend::feCable:
1061                                         {
1062                                                 clearCable=true;
1063                                                 break;
1064                                         }
1065                                 }
1066                         }
1067                 }
1068
1069                 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
1070                 {
1071                         if (m_flags & scanDontRemoveUnscanned)
1072                                 db->removeServices(&(*(*it)));
1073                         else
1074                         {
1075                                 int system;
1076                                 (*it)->getSystem(system);
1077                                 switch(system)
1078                                 {
1079                                         case iDVBFrontend::feSatellite:
1080                                         {
1081                                                 eDVBFrontendParametersSatellite sat_parm;
1082                                                 (*it)->getDVBS(sat_parm);
1083                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
1084                                                 break;
1085                                         }
1086                                         case iDVBFrontend::feTerrestrial:
1087                                         {
1088                                                 clearTerrestrial=true;
1089                                                 break;
1090                                         }
1091                                         case iDVBFrontend::feCable:
1092                                         {
1093                                                 clearCable=true;
1094                                                 break;
1095                                         }
1096                                 }
1097                         }
1098                 }
1099
1100                 if (clearTerrestrial)
1101                 {
1102                         eDVBChannelID chid;
1103                         chid.dvbnamespace=0xEEEE0000;
1104                         db->removeServices(chid);
1105                 }
1106                 if (clearCable)
1107                 {
1108                         eDVBChannelID chid;
1109                         chid.dvbnamespace=0xFFFF0000;
1110                         db->removeServices(chid);
1111                 }
1112                 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
1113                 {
1114                         eDVBChannelID chid;
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);
1119                 }
1120         }
1121
1122         for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator 
1123                         ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
1124         {
1125                 int system;
1126                 ch->second->getSystem(system);
1127                 std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
1128
1129                 switch(system)
1130                 {
1131                         case iDVBFrontend::feTerrestrial:
1132                         {
1133                                 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
1134                                 eDVBFrontendParametersTerrestrial parm;
1135                                 int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
1136                                 p->getDVBT(parm);
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;
1141                                 p->setDVBT(parm);
1142                                 break;
1143                         }
1144                         case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
1145                         case iDVBFrontend::feCable:
1146                                 break;
1147                 }
1148
1149                 if (m_flags & scanOnlyFree)
1150                 {
1151                         eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
1152                         ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
1153                 }
1154
1155                 db->addChannelToList(ch->first, ch->second);
1156         }
1157
1158         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
1159                 service(m_new_services.begin()); service != m_new_services.end(); ++service)
1160         {
1161                 ePtr<eDVBService> dvb_service;
1162                 if (!db->getService(service->first, dvb_service))
1163                 {
1164                         if (dvb_service->m_flags & eDVBService::dxNoSDT)
1165                                 continue;
1166                         if (!(dvb_service->m_flags & eDVBService::dxHoldName))
1167                         {
1168                                 dvb_service->m_service_name = service->second->m_service_name;
1169                                 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
1170                         }
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;
1176                 }
1177                 else
1178                 {
1179                         db->addService(service->first, service->second);
1180                         if (!(m_flags & scanRemoveServices))
1181                                 service->second->m_flags |= eDVBService::dxNewFound;
1182                 }
1183         }
1184 }
1185
1186 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1187 {
1188         const ServiceDescriptionList &services = *sdt.getDescriptions();
1189         SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1190         eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1191         
1192         /* save correct CHID for this channel */
1193         m_chid_current = chid;
1194
1195         for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1196         {
1197                 unsigned short service_id = (*s)->getServiceId();
1198                 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1199                 bool add = true;
1200
1201                 if (m_flags & scanOnlyFree)
1202                 {
1203                         std::map<unsigned short, service>::iterator it =
1204                                 m_pmts_to_read.find(service_id);
1205                         if (it != m_pmts_to_read.end())
1206                         {
1207                                 if (it->second.scrambled)
1208                                 {
1209                                         SCAN_eDebug("is scrambled!");
1210                                         add = false;
1211                                 }
1212                                 else
1213                                         SCAN_eDebug("is free");
1214                         }
1215                         else {
1216                                 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1217                                 add = false;
1218                         }
1219                 }
1220
1221                 if (add)
1222                 {
1223                         eServiceReferenceDVB ref;
1224                         ePtr<eDVBService> service = new eDVBService;
1225
1226                         ref.set(chid);
1227                         ref.setServiceID(service_id);
1228
1229                         for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1230                                         desc != (*s)->getDescriptors()->end(); ++desc)
1231                         {
1232                                 switch ((*desc)->getTag())
1233                                 {
1234                                 case SERVICE_DESCRIPTOR:
1235                                 {
1236                                         ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1237                                         ref.setServiceType(d.getServiceType());
1238                                         service->m_service_name = convertDVBUTF8(d.getServiceName());
1239                                         service->genSortName();
1240
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());
1243                                         break;
1244                                 }
1245                                 case CA_IDENTIFIER_DESCRIPTOR:
1246                                 {
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)
1251                                         {
1252                                                 SCAN_eDebugNoNewLine("%04x ", *i);
1253                                                 service->m_ca.push_front(*i);
1254                                         }
1255                                         SCAN_eDebug("");
1256                                         break;
1257                                 }
1258                                 default:
1259                                         SCAN_eDebug("descr<%x>", (*desc)->getTag());
1260                                         break;
1261                                 }
1262                         }
1263
1264                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1265                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1266
1267                         if (i.second)
1268                         {
1269                                 m_last_service = i.first;
1270                                 m_event(evtNewService);
1271                         }
1272                 }
1273                 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1274                         m_abort_current_pmt = true;
1275                 else
1276                         m_pmts_to_read.erase(service_id);
1277         }
1278
1279         return 0;
1280 }
1281
1282 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1283 {
1284         connection = new eConnection(this, m_event.connect(event));
1285         return 0;
1286 }
1287
1288 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1289 {
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();
1293 }
1294
1295 void eDVBScan::getLastServiceName(std::string &last_service_name)
1296 {
1297         if (m_last_service == m_new_services.end())
1298                 last_service_name = "";
1299         else
1300                 last_service_name = m_last_service->second->m_service_name;
1301 }
1302
1303 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1304 {
1305         if (m_channel)
1306                 return m_channel->getFrontend(fe);
1307         fe = 0;
1308         return -1;
1309 }
1310
1311 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)
1312 {
1313         if (m_ch_current)
1314         {
1315                 tp = m_ch_current;
1316                 return 0;
1317         }
1318         tp = 0;
1319         return -1;
1320 }