46236dd7ad311d014bc1866ec2f2ddf25e82b80e
[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                                         eDVBFrontendParametersSatellite parm;
872                                         m_ch_current->getDVBS(parm);
873                                         snprintf(sname, 255, "%d%c SID 0x%02x",
874                                                         parm.frequency/1000,
875                                                         parm.polarisation ? 'V' : 'H',
876                                                         m_pmt_in_progress->first);
877                                         snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
878                                                 parm.system ? "DVB-S2" : "DVB-S",
879                                                 parm.modulation == 1 ? "QPSK" : "8PSK",
880                                                 parm.frequency/1000,
881                                                 parm.polarisation ? 'V' : 'H',
882                                                 parm.orbital_position/10,
883                                                 parm.orbital_position%10,
884                                                 parm.orbital_position > 0 ? 'E' : 'W');
885                                         break;
886                                 }
887                                 case iDVBFrontend::feTerrestrial:
888                                 {
889                                         eDVBFrontendParametersTerrestrial parm;
890                                         m_ch_current->getDVBT(parm);
891                                         snprintf(sname, 255, "%d SID 0x%02x",
892                                                 parm.frequency/1000,
893                                                 m_pmt_in_progress->first);
894                                         break;
895                                 }
896                                 case iDVBFrontend::feCable:
897                                 {
898                                         eDVBFrontendParametersCable parm;
899                                         m_ch_current->getDVBC(parm);
900                                         snprintf(sname, 255, "%d SID 0x%02x",
901                                                 parm.frequency/1000,
902                                                 m_pmt_in_progress->first);
903                                         break;
904                                 }
905                         }
906                         SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
907                         service->m_service_name = convertDVBUTF8(sname);
908                         service->genSortName();
909                         service->m_provider_name = convertDVBUTF8(pname);
910                 }
911
912                 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
913                         SCAN_eDebug("add not scrambled!");
914                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
915                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
916                         if (i.second)
917                         {
918                                 m_last_service = i.first;
919                                 m_event(evtNewService);
920                         }
921                 }
922                 else
923                         SCAN_eDebug("dont add... is scrambled!");
924                 m_pmts_to_read.erase(m_pmt_in_progress++);
925         }
926
927         if (!m_chid_current)
928                 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
929         else
930         {
931                 addKnownGoodChannel(m_chid_current, m_ch_current);
932                 if (m_chid_current)
933                 {
934                         switch(type)
935                         {
936                                 case iDVBFrontend::feSatellite:
937                                 case iDVBFrontend::feTerrestrial:
938                                 case iDVBFrontend::feCable:
939                                 {
940                                         ePtr<iDVBFrontend> fe;
941                                         if (!m_channel->getFrontend(fe))
942                                         {
943                                                 ePyObject tp_dict = PyDict_New();
944                                                 fe->getTransponderData(tp_dict, false);
945 //                                              eDebug("add tuner data for tsid %04x, onid %04x, ns %08x",
946 //                                                      m_chid_current.transport_stream_id.get(), m_chid_current.original_network_id.get(),
947 //                                                      m_chid_current.dvbnamespace.get());
948                                                 m_tuner_data.insert(std::pair<eDVBChannelID, ePyObjectWrapper>(m_chid_current, tp_dict));
949                                                 Py_DECREF(tp_dict);
950                                         }
951                                 }
952                                 default:
953                                         break;
954                         }
955                 }
956         }
957
958         m_ch_scanned.push_back(m_ch_current);
959
960         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
961         {
962                 if (sameChannel(*i, m_ch_current))
963                 {
964                         SCAN_eDebug("remove dupe 2");
965                         m_ch_toScan.erase(i++);
966                         continue;
967                 }
968                 ++i;
969         }
970         
971         nextChannel();
972 }
973
974 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
975 {
976         m_flags = flags;
977         m_ch_toScan.clear();
978         m_ch_scanned.clear();
979         m_ch_unavailable.clear();
980         m_new_channels.clear();
981         m_tuner_data.clear();
982         m_new_services.clear();
983         m_last_service = m_new_services.end();
984
985         for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
986         {
987                 bool exist=false;
988                 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
989                 {
990                         if (sameChannel(*i, *ii, true))
991                         {
992                                 exist=true;
993                                 break;
994                         }
995                 }
996                 if (!exist)
997                         m_ch_toScan.push_back(*i);
998         }
999
1000         nextChannel();
1001 }
1002
1003 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
1004 {
1005         if (m_flags & scanRemoveServices)
1006         {
1007                 bool clearTerrestrial=false;
1008                 bool clearCable=false;
1009                 std::set<unsigned int> scanned_sat_positions;
1010                 
1011                 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
1012                 for (;it != m_ch_scanned.end(); ++it)
1013                 {
1014                         if (m_flags & scanDontRemoveUnscanned)
1015                                 db->removeServices(&(*(*it)));
1016                         else
1017                         {
1018                                 int system;
1019                                 (*it)->getSystem(system);
1020                                 switch(system)
1021                                 {
1022                                         case iDVBFrontend::feSatellite:
1023                                         {
1024                                                 eDVBFrontendParametersSatellite sat_parm;
1025                                                 (*it)->getDVBS(sat_parm);
1026                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
1027                                                 break;
1028                                         }
1029                                         case iDVBFrontend::feTerrestrial:
1030                                         {
1031                                                 clearTerrestrial=true;
1032                                                 break;
1033                                         }
1034                                         case iDVBFrontend::feCable:
1035                                         {
1036                                                 clearCable=true;
1037                                                 break;
1038                                         }
1039                                 }
1040                         }
1041                 }
1042
1043                 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
1044                 {
1045                         if (m_flags & scanDontRemoveUnscanned)
1046                                 db->removeServices(&(*(*it)));
1047                         else
1048                         {
1049                                 int system;
1050                                 (*it)->getSystem(system);
1051                                 switch(system)
1052                                 {
1053                                         case iDVBFrontend::feSatellite:
1054                                         {
1055                                                 eDVBFrontendParametersSatellite sat_parm;
1056                                                 (*it)->getDVBS(sat_parm);
1057                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
1058                                                 break;
1059                                         }
1060                                         case iDVBFrontend::feTerrestrial:
1061                                         {
1062                                                 clearTerrestrial=true;
1063                                                 break;
1064                                         }
1065                                         case iDVBFrontend::feCable:
1066                                         {
1067                                                 clearCable=true;
1068                                                 break;
1069                                         }
1070                                 }
1071                         }
1072                 }
1073
1074                 if (clearTerrestrial)
1075                 {
1076                         eDVBChannelID chid;
1077                         chid.dvbnamespace=0xEEEE0000;
1078                         db->removeServices(chid);
1079                 }
1080                 if (clearCable)
1081                 {
1082                         eDVBChannelID chid;
1083                         chid.dvbnamespace=0xFFFF0000;
1084                         db->removeServices(chid);
1085                 }
1086                 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
1087                 {
1088                         eDVBChannelID chid;
1089                         if (m_flags & scanDontRemoveFeeds)
1090                                 chid.dvbnamespace = eDVBNamespace((*x)<<16);
1091 //                      eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
1092                         db->removeServices(chid, *x);
1093                 }
1094         }
1095
1096         for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator 
1097                         ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
1098         {
1099                 int system;
1100                 ch->second->getSystem(system);
1101                 std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
1102
1103                 switch(system)
1104                 {
1105                         case iDVBFrontend::feTerrestrial:
1106                         {
1107                                 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
1108                                 eDVBFrontendParametersTerrestrial parm;
1109                                 int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
1110                                 p->getDVBT(parm);
1111 //                              eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
1112 //                                      ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
1113 //                                      ch->first.dvbnamespace.get(), freq, parm.frequency);
1114                                 parm.frequency = freq;
1115                                 p->setDVBT(parm);
1116                                 break;
1117                         }
1118                         case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
1119                         case iDVBFrontend::feCable:
1120                                 break;
1121                 }
1122
1123                 if (m_flags & scanOnlyFree)
1124                 {
1125                         eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
1126                         ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
1127                 }
1128
1129                 db->addChannelToList(ch->first, ch->second);
1130         }
1131
1132         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
1133                 service(m_new_services.begin()); service != m_new_services.end(); ++service)
1134         {
1135                 ePtr<eDVBService> dvb_service;
1136                 if (!db->getService(service->first, dvb_service))
1137                 {
1138                         if (dvb_service->m_flags & eDVBService::dxNoSDT)
1139                                 continue;
1140                         if (!(dvb_service->m_flags & eDVBService::dxHoldName))
1141                         {
1142                                 dvb_service->m_service_name = service->second->m_service_name;
1143                                 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
1144                         }
1145                         dvb_service->m_provider_name = service->second->m_provider_name;
1146                         if (service->second->m_ca.size())
1147                                 dvb_service->m_ca = service->second->m_ca;
1148                         if (!dontRemoveOldFlags) // do not remove new found flags when not wished
1149                                 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1150                 }
1151                 else
1152                 {
1153                         db->addService(service->first, service->second);
1154                         if (!(m_flags & scanRemoveServices))
1155                                 service->second->m_flags |= eDVBService::dxNewFound;
1156                 }
1157         }
1158 }
1159
1160 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1161 {
1162         const ServiceDescriptionList &services = *sdt.getDescriptions();
1163         SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1164         eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1165         
1166         /* save correct CHID for this channel */
1167         m_chid_current = chid;
1168
1169         for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1170         {
1171                 unsigned short service_id = (*s)->getServiceId();
1172                 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1173                 bool add = true;
1174
1175                 if (m_flags & scanOnlyFree)
1176                 {
1177                         std::map<unsigned short, service>::iterator it =
1178                                 m_pmts_to_read.find(service_id);
1179                         if (it != m_pmts_to_read.end())
1180                         {
1181                                 if (it->second.scrambled)
1182                                 {
1183                                         SCAN_eDebug("is scrambled!");
1184                                         add = false;
1185                                 }
1186                                 else
1187                                         SCAN_eDebug("is free");
1188                         }
1189                         else {
1190                                 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1191                                 add = false;
1192                         }
1193                 }
1194
1195                 if (add)
1196                 {
1197                         eServiceReferenceDVB ref;
1198                         ePtr<eDVBService> service = new eDVBService;
1199
1200                         ref.set(chid);
1201                         ref.setServiceID(service_id);
1202
1203                         for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1204                                         desc != (*s)->getDescriptors()->end(); ++desc)
1205                         {
1206                                 switch ((*desc)->getTag())
1207                                 {
1208                                 case SERVICE_DESCRIPTOR:
1209                                 {
1210                                         ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1211                                         ref.setServiceType(d.getServiceType());
1212                                         service->m_service_name = convertDVBUTF8(d.getServiceName());
1213                                         service->genSortName();
1214
1215                                         service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1216                                         SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1217                                         break;
1218                                 }
1219                                 case CA_IDENTIFIER_DESCRIPTOR:
1220                                 {
1221                                         CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1222                                         const CaSystemIdList &caids = *d.getCaSystemIds();
1223                                         SCAN_eDebugNoNewLine("CA ");
1224                                         for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1225                                         {
1226                                                 SCAN_eDebugNoNewLine("%04x ", *i);
1227                                                 service->m_ca.push_front(*i);
1228                                         }
1229                                         SCAN_eDebug("");
1230                                         break;
1231                                 }
1232                                 default:
1233                                         SCAN_eDebug("descr<%x>", (*desc)->getTag());
1234                                         break;
1235                                 }
1236                         }
1237
1238                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1239                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1240
1241                         if (i.second)
1242                         {
1243                                 m_last_service = i.first;
1244                                 m_event(evtNewService);
1245                         }
1246                 }
1247                 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1248                         m_abort_current_pmt = true;
1249                 else
1250                         m_pmts_to_read.erase(service_id);
1251         }
1252
1253         return 0;
1254 }
1255
1256 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1257 {
1258         connection = new eConnection(this, m_event.connect(event));
1259         return 0;
1260 }
1261
1262 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1263 {
1264         transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1265         transponders_total = m_ch_toScan.size() + transponders_done;
1266         services = m_new_services.size();
1267 }
1268
1269 void eDVBScan::getLastServiceName(std::string &last_service_name)
1270 {
1271         if (m_last_service == m_new_services.end())
1272                 last_service_name = "";
1273         else
1274                 last_service_name = m_last_service->second->m_service_name;
1275 }
1276
1277 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1278 {
1279         if (m_channel)
1280                 return m_channel->getFrontend(fe);
1281         fe = 0;
1282         return -1;
1283 }
1284
1285 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)
1286 {
1287         if (m_ch_current)
1288         {
1289                 tp = m_ch_current;
1290                 return 0;
1291         }
1292         tp = 0;
1293         return -1;
1294 }