update dvbapp.
[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++/cable_delivery_system_descriptor.h>
7 #include <dvbsi++/ca_identifier_descriptor.h>
8 #include <dvbsi++/registration_descriptor.h>
9 #include <lib/dvb/specs.h>
10 #include <lib/dvb/esection.h>
11 #include <lib/dvb/scan.h>
12 #include <lib/dvb/frontend.h>
13 #include <lib/base/eenv.h>
14 #include <lib/base/eerror.h>
15 #include <lib/base/estring.h>
16 #include <lib/python/python.h>
17 #include <errno.h>
18
19 #define SCAN_eDebug(x...) do { if (m_scan_debug) eDebug(x); } while(0)
20 #define SCAN_eDebugNoNewLine(x...) do { if (m_scan_debug) eDebugNoNewLine(x); } while(0)
21
22 DEFINE_REF(eDVBScan);
23
24 eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug)
25         :m_channel(channel), m_channel_state(iDVBChannel::state_idle)
26         ,m_ready(0), m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT)
27         ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0)
28         ,m_usePAT(usePAT), m_scan_debug(debug), m_show_add_tsid_onid_check_failed_msg(true)
29 {
30         if (m_channel->getDemux(m_demux))
31                 SCAN_eDebug("scan: failed to allocate demux!");
32         m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
33         std::string filename = eEnv::resolve("${sysconfdir}/scan_tp_valid_check.py");
34         FILE *f = fopen(filename.c_str(), "r");
35         if (f)
36         {
37                 char code[16384];
38                 size_t rd = fread(code, 1, 16383, f);
39                 if (rd)
40                 {
41                         code[rd]=0;
42                         m_additional_tsid_onid_check_func = Py_CompileString(code, filename.c_str(), Py_file_input);
43                 }
44                 fclose(f);
45         }
46 }
47
48 eDVBScan::~eDVBScan()
49 {
50         if (m_additional_tsid_onid_check_func)
51                 Py_DECREF(m_additional_tsid_onid_check_func);
52 }
53
54 int eDVBScan::isValidONIDTSID(int orbital_position, eOriginalNetworkID onid, eTransportStreamID tsid)
55 {
56         int ret;
57         switch (onid.get())
58         {
59         case 0:
60         case 0x1111:
61                 ret=0;
62                 break;
63         case 0x13E:  // workaround for 11258H and 11470V on hotbird with same ONID/TSID (0x13E/0x578)
64                 ret = orbital_position != 130 || tsid != 0x578;
65                 break;
66         case 1:
67                 ret = orbital_position == 192;
68                 break;
69         case 0x00B1:
70                 ret = tsid != 0x00B0;
71                 break;
72         case 0x00eb:
73                 ret = tsid != 0x4321;
74                 break;
75         case 0x0002:
76                 ret = abs(orbital_position-282) < 6 && tsid != 2019;
77                 // 12070H and 10936V have same tsid/onid.. but even the same services are provided
78                 break;
79         case 0x2000:
80                 ret = tsid != 0x1000;
81                 break;
82         case 0x5E: // Sirius 4.8E 12322V and 12226H
83                 ret = abs(orbital_position-48) < 3 && tsid != 1;
84                 break;
85         case 10100: // Eutelsat W7 36.0E 11644V and 11652V
86                 ret = orbital_position != 360 || tsid != 10187;
87                 break;
88         case 42: // Tuerksat 42.0E
89                 ret = orbital_position != 420 || (
90                     tsid != 8 && // 11830V 12729V
91                     tsid != 5 && // 12679V 12685H
92                     tsid != 2 && // 11096V 12015H
93                     tsid != 55); // 11996V 11716V
94                 break;
95         case 100: // Intelsat 10 68.5E 3808V 3796V 4012V, Amos 4.0W 10723V 11571H
96                 ret = (orbital_position != 685 && orbital_position != 3560) || tsid != 1;
97                 break;
98         case 70: // Thor 0.8W 11862H 12341V
99                 ret = abs(orbital_position-3592) < 3 && tsid != 46;
100                 break;
101         case 32: // NSS 806 (40.5W) 4059R, 3774L
102                 ret = orbital_position != 3195 || tsid != 21;
103                 break;
104         default:
105                 ret = onid.get() < 0xFF00;
106                 break;
107         }
108         if (ret && m_additional_tsid_onid_check_func)
109         {
110                 bool failed = true;
111                 ePyObject dict = PyDict_New();
112                 extern void PutToDict(ePyObject &, const char *, long);
113                 PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
114                 PutToDict(dict, "orbpos", orbital_position);
115                 PutToDict(dict, "tsid", tsid.get());
116                 PutToDict(dict, "onid", onid.get());
117                 ePyObject r = PyEval_EvalCode((PyCodeObject*)(PyObject*)m_additional_tsid_onid_check_func, dict, dict);
118                 if (r)
119                 {
120                         ePyObject o = PyDict_GetItemString(dict, "ret");
121                         if (o)
122                         {
123                                 if (PyInt_Check(o))
124                                 {
125                                         ret = PyInt_AsLong(o);
126                                         failed = false;
127                                 }
128                         }
129                         Py_DECREF(r);
130                 }
131                 if (failed && m_show_add_tsid_onid_check_failed_msg)
132                 {
133                         eDebug("execing /etc/enigma2/scan_tp_valid_check failed!\n"
134                                 "usable global variables in scan_tp_valid_check.py are 'orbpos', 'tsid', 'onid'\n"
135                                 "the return value must be stored in a global var named 'ret'");
136                         m_show_add_tsid_onid_check_failed_msg=false;
137                 }
138                 Py_DECREF(dict);
139         }
140         return ret;
141 }
142
143 eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash)
144 {
145                 // on valid ONIDs, ignore frequency ("sub network") part
146         if (isValidONIDTSID((hash >> 16) & 0xFFFF, onid, tsid))
147                 hash &= ~0xFFFF;
148         return eDVBNamespace(hash);
149 }
150
151 void eDVBScan::stateChange(iDVBChannel *ch)
152 {
153         int state;
154         if (ch->getState(state))
155                 return;
156         if (m_channel_state == state)
157                 return;
158         
159         if (state == iDVBChannel::state_ok)
160         {
161                 startFilter();
162                 m_channel_state = state;
163         } else if (state == iDVBChannel::state_failed)
164         {
165                 m_ch_unavailable.push_back(m_ch_current);
166                 nextChannel();
167         }
168                         /* unavailable will timeout, anyway. */
169 }
170
171 RESULT eDVBScan::nextChannel()
172 {
173         ePtr<iDVBFrontend> fe;
174
175         m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0;
176
177         m_ready = 0;
178
179         m_pat_tsid = eTransportStreamID();
180
181                 /* check what we need */
182         m_ready_all = readySDT;
183         
184         if (m_flags & scanNetworkSearch)
185                 m_ready_all |= readyNIT;
186         
187         if (m_flags & scanSearchBAT)
188                 m_ready_all |= readyBAT;
189
190         if (m_usePAT)
191                 m_ready_all |= readyPAT;
192
193         if (m_ch_toScan.empty())
194         {
195                 SCAN_eDebug("no channels left to scan.");
196                 SCAN_eDebug("%zd channels scanned, %zd were unavailable.",
197                                 m_ch_scanned.size(), m_ch_unavailable.size());
198                 SCAN_eDebug("%zd channels in database.", m_new_channels.size());
199                 m_event(evtFinish);
200                 return -ENOENT;
201         }
202         
203         m_ch_current = m_ch_toScan.front();
204         
205         m_ch_toScan.pop_front();
206         
207         if (m_channel->getFrontend(fe))
208         {
209                 m_event(evtFail);
210                 return -ENOTSUP;
211         }
212
213         m_chid_current = eDVBChannelID();
214
215         m_channel_state = iDVBChannel::state_idle;
216
217         if (fe->tune(*m_ch_current))
218                 return nextChannel();
219
220         m_event(evtUpdate);
221         return 0;
222 }
223
224 RESULT eDVBScan::startFilter()
225 {
226         bool startSDT=true;
227         ASSERT(m_demux);
228
229                         /* only start required filters filter */
230
231         if (m_ready_all & readyPAT)
232                 startSDT = m_ready & readyPAT;
233
234         // m_ch_current is not set, when eDVBScan is just used for a SDT update
235         if (!m_ch_current)
236         {
237                 unsigned int channelFlags;
238                 m_channel->getCurrentFrontendParameters(m_ch_current);
239                 m_ch_current->getFlags(channelFlags);
240                 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
241                         m_flags |= scanOnlyFree;
242         }
243
244         m_SDT = 0;
245         if (startSDT && (m_ready_all & readySDT))
246         {
247                 m_SDT = new eTable<ServiceDescriptionSection>(m_scan_debug);
248                 int tsid=-1;
249                 if (m_ready & readyPAT && m_ready & validPAT)
250                 {
251                         std::vector<ProgramAssociationSection*>::const_iterator i =
252                                 m_PAT->getSections().begin();
253                         ASSERT(i != m_PAT->getSections().end());
254                         tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
255                         m_pat_tsid = eTransportStreamID(tsid);
256                         for (; i != m_PAT->getSections().end(); ++i)
257                         {
258                                 const ProgramAssociationSection &pat = **i;
259                                 ProgramAssociationConstIterator program = pat.getPrograms()->begin();
260                                 for (; program != pat.getPrograms()->end(); ++program)
261                                         m_pmts_to_read.insert(std::pair<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
262                         }
263                         m_PMT = new eTable<ProgramMapSection>(m_scan_debug);
264                         CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
265                         PMTready(-2);
266                         // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
267
268                         {
269                                 int type;
270                                 m_ch_current->getSystem(type);
271                                 if (type == iDVBFrontend::feCable)
272                                 {
273                                         eDVBFrontendParametersCable parm;
274                                         m_ch_current->getDVBC(parm);
275                                         if ((tsid == 0x00d7 && abs(parm.frequency-618000) < 2000) ||
276                                                 (tsid == 0x00d8 && abs(parm.frequency-626000) < 2000))
277                                                 tsid = -1;
278                                 }
279                         }
280                 }
281                 if (tsid == -1)
282                 {
283                         if (m_SDT->start(m_demux, eDVBSDTSpec()))
284                                 return -1;
285                 }
286                 else if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
287                         return -1;
288                 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
289         }
290
291         if (!(m_ready & readyPAT))
292         {
293                 m_PAT = 0;
294                 if (m_ready_all & readyPAT)
295                 {
296                         m_PAT = new eTable<ProgramAssociationSection>(m_scan_debug);
297                         if (m_PAT->start(m_demux, eDVBPATSpec(4000)))
298                                 return -1;
299                         CONNECT(m_PAT->tableReady, eDVBScan::PATready);
300                 }
301
302                 m_NIT = 0;
303                 if (m_ready_all & readyNIT)
304                 {
305                         m_NIT = new eTable<NetworkInformationSection>(m_scan_debug);
306                         if (m_NIT->start(m_demux, eDVBNITSpec()))
307                                 return -1;
308                         CONNECT(m_NIT->tableReady, eDVBScan::NITready);
309                 }
310
311                 m_BAT = 0;
312                 if (m_ready_all & readyBAT)
313                 {
314                         m_BAT = new eTable<BouquetAssociationSection>(m_scan_debug);
315                         if (m_BAT->start(m_demux, eDVBBATSpec()))
316                                 return -1;
317                         CONNECT(m_BAT->tableReady, eDVBScan::BATready);
318                 }
319         }
320         return 0;
321 }
322
323 void eDVBScan::SDTready(int err)
324 {
325         SCAN_eDebug("got sdt %d", err);
326         m_ready |= readySDT;
327         if (!err)
328                 m_ready |= validSDT;
329         channelDone();
330 }
331
332 void eDVBScan::NITready(int err)
333 {
334         SCAN_eDebug("got nit, err %d", err);
335         m_ready |= readyNIT;
336         if (!err)
337                 m_ready |= validNIT;
338         channelDone();
339 }
340
341 void eDVBScan::BATready(int err)
342 {
343         SCAN_eDebug("got bat");
344         m_ready |= readyBAT;
345         if (!err)
346                 m_ready |= validBAT;
347         channelDone();
348 }
349
350 void eDVBScan::PATready(int err)
351 {
352         SCAN_eDebug("got pat");
353         m_ready |= readyPAT;
354         if (!err)
355                 m_ready |= validPAT;
356         startFilter(); // for starting the SDT filter
357 }
358
359 void eDVBScan::PMTready(int err)
360 {
361         SCAN_eDebug("got pmt %d", err);
362         if (!err)
363         {
364                 bool scrambled = false;
365                 bool have_audio = false;
366                 bool have_video = false;
367                 unsigned short pcrpid = 0xFFFF;
368                 std::vector<ProgramMapSection*>::const_iterator i;
369
370                 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
371                 {
372                         const ProgramMapSection &pmt = **i;
373                         if (pcrpid == 0xFFFF)
374                                 pcrpid = pmt.getPcrPid();
375                         else
376                                 SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
377                         ElementaryStreamInfoConstIterator es;
378                         for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
379                         {
380                                 int isaudio = 0, isvideo = 0, is_scrambled = 0, forced_audio = 0, forced_video = 0;
381                                 switch ((*es)->getType())
382                                 {
383                                 case 0x1b: // AVC Video Stream (MPEG4 H264)
384                                 case 0x24: // H265 HEVC
385                                 case 0x10: // MPEG 4 Part 2
386                                 case 0x01: // MPEG 1 video
387                                 case 0x02: // MPEG 2 video
388                                         isvideo = 1;
389                                         forced_video = 1;
390                                         //break; fall through !!!
391                                 case 0x03: // MPEG 1 audio
392                                 case 0x04: // MPEG 2 audio
393                                 case 0x0f: // MPEG 2 AAC
394                                 case 0x11: // MPEG 4 AAC
395                                         if (!isvideo) 
396                                         {
397                                                 forced_audio = 1;
398                                                 isaudio = 1;
399                                         }
400                                 case 0x06: // PES Private
401                                 case 0x81: // user private
402                                 case 0xEA: // TS_PSI_ST_SMPTE_VC1
403                                         for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
404                                                         desc != (*es)->getDescriptors()->end(); ++desc)
405                                         {
406                                                 uint8_t tag = (*desc)->getTag();
407                                                 /* PES private can contain AC-3, DTS or lots of other stuff.
408                                                    check descriptors to get the exakt type. */
409                                                 if (!forced_video && !forced_audio)
410                                                 {
411                                                         switch (tag)
412                                                         {
413                                                         case 0x1C: // TS_PSI_DT_MPEG4_Audio
414                                                         case 0x2B: // TS_PSI_DT_MPEG2_AAC
415                                                         case AAC_DESCRIPTOR:
416                                                         case AC3_DESCRIPTOR:
417                                                         case DTS_DESCRIPTOR:
418                                                         case AUDIO_STREAM_DESCRIPTOR:
419                                                                 isaudio = 1;
420                                                                 break;
421                                                         case 0x28: // TS_PSI_DT_AVC
422                                                         case 0x1B: // TS_PSI_DT_MPEG4_Video
423                                                         case VIDEO_STREAM_DESCRIPTOR:
424                                                                 isvideo = 1;
425                                                                 break;
426                                                         case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
427                                                         {
428                                                                 RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc);
429                                                                 switch (d->getFormatIdentifier())
430                                                                 {
431                                                                 case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
432                                                                 case 0x41432d33: // == 'AC-3'
433                                                                 case 0x42535344: // == 'BSSD' (LPCM)
434                                                                         isaudio = 1;
435                                                                         break;
436                                                                 case 0x56432d31: // == 'VC-1'
437                                                                         isvideo = 1;
438                                                                         break;
439                                                                 default:
440                                                                         break;
441                                                                 }
442                                                         }
443                                                         default:
444                                                                 break;
445                                                         }
446                                                 }
447                                                 if (tag == CA_DESCRIPTOR)
448                                                         is_scrambled = 1;
449                                         }
450                                 default:
451                                         break;
452                                 }
453                                 if (isvideo)
454                                         have_video = true;
455                                 else if (isaudio)
456                                         have_audio = true;
457                                 else
458                                         continue;
459                                 if (is_scrambled)
460                                         scrambled = true;
461                         }
462                         for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
463                                 desc != pmt.getDescriptors()->end(); ++desc)
464                         {
465                                 if ((*desc)->getTag() == CA_DESCRIPTOR)
466                                         scrambled = true;
467                         }
468                 }
469                 m_pmt_in_progress->second.scrambled = scrambled;
470                 if ( have_video )
471                         m_pmt_in_progress->second.serviceType = 1;
472                 else if ( have_audio )
473                         m_pmt_in_progress->second.serviceType = 2;
474                 else
475                         m_pmt_in_progress->second.serviceType = 100;
476         }
477         if (err == -1) // timeout or removed by sdt
478                 m_pmts_to_read.erase(m_pmt_in_progress++);
479         else if (m_pmt_running)
480                 ++m_pmt_in_progress;
481         else
482         {
483                 m_pmt_in_progress = m_pmts_to_read.begin();
484                 m_pmt_running = true;
485         }
486
487         if (m_pmt_in_progress != m_pmts_to_read.end())
488                 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
489         else
490         {
491                 m_PMT = 0;
492                 m_pmt_running = false;
493                 channelDone();
494         }
495 }
496
497
498 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
499 {
500                 /* add it to the list of known channels. */
501         if (chid)
502                 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
503 }
504
505 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
506 {
507                 /* check if we don't already have that channel ... */
508
509         int type;
510         feparm->getSystem(type);
511
512         switch(type)
513         {
514         case iDVBFrontend::feSatellite:
515         {
516                 eDVBFrontendParametersSatellite parm;
517                 feparm->getDVBS(parm);
518                 SCAN_eDebug("try to add %d %d %d %d %d %d",
519                         parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
520                 break;
521         }
522         case iDVBFrontend::feCable:
523         {
524                 eDVBFrontendParametersCable parm;
525                 feparm->getDVBC(parm);
526                 SCAN_eDebug("try to add %d %d %d %d",
527                         parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
528                 break;
529         }
530         case iDVBFrontend::feTerrestrial:
531         {
532                 eDVBFrontendParametersTerrestrial parm;
533                 feparm->getDVBT(parm);
534                 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
535                         parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
536                         parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
537                 break;
538         }
539         }
540
541         int found_count=0;
542                 /* ... in the list of channels to scan */
543         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
544         {
545                 if (sameChannel(*i, feparm))
546                 {
547                         if (!found_count)
548                         {
549                                 *i = feparm;  // update
550                                 SCAN_eDebug("update");
551                         }
552                         else
553                         {
554                                 SCAN_eDebug("remove dupe");
555                                 m_ch_toScan.erase(i++);
556                                 continue;
557                         }
558                         ++found_count;
559                 }
560                 ++i;
561         }
562
563         if (found_count > 0)
564         {
565                 SCAN_eDebug("already in todo list");
566                 return;
567         }
568
569                 /* ... in the list of successfully scanned channels */
570         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
571                 if (sameChannel(*i, feparm))
572                 {
573                         SCAN_eDebug("successfully scanned");
574                         return;
575                 }
576
577                 /* ... in the list of unavailable channels */
578         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
579                 if (sameChannel(*i, feparm, true))
580                 {
581                         SCAN_eDebug("scanned but not available");
582                         return;
583                 }
584
585                 /* ... on the current channel */
586         if (sameChannel(m_ch_current, feparm))
587         {
588                 SCAN_eDebug("is current");
589                 return;
590         }
591
592         SCAN_eDebug("really add");
593                 /* otherwise, add it to the todo list. */
594         m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
595 }
596
597 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
598 {
599         int diff;
600         if (ch1->calculateDifference(ch2, diff, exact))
601                 return 0;
602         if (diff < 4000) // more than 4mhz difference?
603                 return 1;
604         return 0;
605 }
606
607 void eDVBScan::channelDone()
608 {
609         if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
610         {
611                 unsigned long hash = 0;
612
613                 m_ch_current->getHash(hash);
614                 
615                 eDVBNamespace dvbnamespace = buildNamespace(
616                         (**m_SDT->getSections().begin()).getOriginalNetworkId(),
617                         (**m_SDT->getSections().begin()).getTransportStreamId(),
618                         hash);
619                 
620                 SCAN_eDebug("SDT: ");
621                 std::vector<ServiceDescriptionSection*>::const_iterator i;
622                 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
623                         processSDT(dvbnamespace, **i);
624                 m_ready &= ~validSDT;
625         }
626         
627         if (m_ready & validNIT)
628         {
629                 int system;
630                 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
631                 m_ch_current->getSystem(system);
632                 SCAN_eDebug("dumping NIT");
633                 if (m_flags & clearToScanOnFirstNIT)
634                 {
635                         m_ch_toScan_backup = m_ch_toScan;
636                         m_ch_toScan.clear();
637                 }
638                 std::vector<NetworkInformationSection*>::const_iterator i;
639                 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
640                 {
641                         const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
642                         
643                         for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin()); 
644                                 tsinfo != tsinfovec.end(); ++tsinfo)
645                         {
646                                 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
647                                         (*tsinfo)->getOriginalNetworkId());
648                                 
649                                 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
650                                 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
651                                 
652                                 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
653                                                 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
654                                 {
655                                         switch ((*desc)->getTag())
656                                         {
657                                         case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
658                                         {
659                                                 if (system != iDVBFrontend::feCable)
660                                                         break; // when current locked transponder is no cable transponder ignore this descriptor
661                                                 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
662                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
663                                                 eDVBFrontendParametersCable cable;
664                                                 cable.set(d);
665                                                 feparm->setDVBC(cable);
666
667                                                 unsigned long hash=0;
668                                                 feparm->getHash(hash);
669                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
670
671                                                 addChannelToScan(
672                                                         eDVBChannelID(ns, tsid, onid),
673                                                         feparm);
674                                                 break;
675                                         }
676                                         case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
677                                         {
678                                                 if (system != iDVBFrontend::feTerrestrial)
679                                                         break; // when current locked transponder is no terrestrial transponder ignore this descriptor
680                                                 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
681                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
682                                                 eDVBFrontendParametersTerrestrial terr;
683                                                 terr.set(d);
684                                                 feparm->setDVBT(terr);
685
686                                                 unsigned long hash=0;
687                                                 feparm->getHash(hash);
688                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
689
690                                                 addChannelToScan(
691                                                         eDVBChannelID(ns, tsid, onid),
692                                                         feparm);
693                                                 break;
694                                         }
695                                         case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
696                                         {
697                                                 if (system != iDVBFrontend::feSatellite)
698                                                         break; // when current locked transponder is no satellite transponder ignore this descriptor
699
700                                                 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
701                                                 if (d.getFrequency() < 10000)
702                                                         break;
703                                                 
704                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
705                                                 eDVBFrontendParametersSatellite sat;
706                                                 sat.set(d);
707
708                                                 eDVBFrontendParametersSatellite p;
709                                                 m_ch_current->getDVBS(p);
710
711                                                 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
712                                                         sat.orbital_position = p.orbital_position;
713
714                                                 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
715                                                 {
716                                                         SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
717                                                         sat.orbital_position = p.orbital_position;
718                                                 }
719
720                                                 feparm->setDVBS(sat);
721
722                                                 if ( p.orbital_position != sat.orbital_position)
723                                                         SCAN_eDebug("dropping this transponder, it's on another satellite.");
724                                                 else
725                                                 {
726                                                         unsigned long hash=0;
727                                                         feparm->getHash(hash);
728                                                         addChannelToScan(
729                                                                         eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
730                                                                         feparm);
731                                                 }
732                                                 break;
733                                         }
734                                         default:
735                                                 SCAN_eDebug("descr<%x>", (*desc)->getTag());
736                                                 break;
737                                         }
738                                 }
739                         }
740                         
741                 }
742
743                         /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
744                            no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
745                            has been found.
746
747                            This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
748                         */
749                 if (m_flags & clearToScanOnFirstNIT)
750                 {
751                         if (m_ch_toScan.empty())
752                         {
753                                 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
754                                 m_ch_toScan = m_ch_toScan_backup;
755                         } else
756                                 m_flags &= ~clearToScanOnFirstNIT;
757                 }
758                 m_ready &= ~validNIT;
759         }
760
761         if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
762         {
763                 if (m_abort_current_pmt)
764                 {
765                         m_abort_current_pmt = false;
766                         PMTready(-1);
767                 }
768                 return;
769         }
770
771         SCAN_eDebug("channel done!");
772         
773                 /* if we had services on this channel, we declare
774                    this channels as "known good". add it.
775                    
776                    (TODO: not yet implemented)
777                    a NIT entry could have possible overridden
778                    our frontend data with more exact data.
779                    
780                    (TODO: not yet implemented)
781                    the tuning process could have lead to more
782                    exact data than the user entered.
783                    
784                    The channel id was probably corrected
785                    by the data written in the SDT. this is
786                    important, as "initial transponder lists"
787                    usually don't have valid CHIDs (and that's
788                    good).
789                    
790                    These are the reasons for adding the transponder
791                    here, and not before.
792                 */
793
794         int type;
795         if (m_ch_current->getSystem(type))
796                 type = -1;
797
798         for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
799         {
800                 eServiceReferenceDVB ref;
801                 ePtr<eDVBService> service = new eDVBService;
802
803                 if (!m_chid_current)
804                 {
805                         unsigned long hash = 0;
806
807                         m_ch_current->getHash(hash);
808
809                         m_chid_current = eDVBChannelID(
810                                 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
811                                 m_pat_tsid, eOriginalNetworkID(0));
812                 }
813
814                 if (m_pmt_in_progress->second.serviceType == 1)
815                         SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
816                 else if (m_pmt_in_progress->second.serviceType == 2)
817                         SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
818                 else
819                         SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
820
821                 ref.set(m_chid_current);
822                 ref.setServiceID(m_pmt_in_progress->first);
823                 ref.setServiceType(m_pmt_in_progress->second.serviceType);
824
825                 if (type != -1)
826                 {
827                         char sname[255];
828                         char pname[255];
829                         memset(pname, 0, sizeof(pname));
830                         memset(sname, 0, sizeof(sname));
831                         switch(type)
832                         {
833                                 case iDVBFrontend::feSatellite:
834                                 {
835                                         eDVBFrontendParametersSatellite parm;
836                                         m_ch_current->getDVBS(parm);
837                                         snprintf(sname, 255, "%d%c SID 0x%02x",
838                                                         parm.frequency/1000,
839                                                         parm.polarisation ? 'V' : 'H',
840                                                         m_pmt_in_progress->first);
841                                         snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
842                                                 parm.system ? "DVB-S2" : "DVB-S",
843                                                 parm.modulation == 1 ? "QPSK" : "8PSK",
844                                                 parm.frequency/1000,
845                                                 parm.polarisation ? 'V' : 'H',
846                                                 parm.orbital_position/10,
847                                                 parm.orbital_position%10,
848                                                 parm.orbital_position > 0 ? 'E' : 'W');
849                                         break;
850                                 }
851                                 case iDVBFrontend::feTerrestrial:
852                                 {
853                                         eDVBFrontendParametersTerrestrial parm;
854                                         m_ch_current->getDVBT(parm);
855                                         snprintf(sname, 255, "%d SID 0x%02x",
856                                                 parm.frequency/1000,
857                                                 m_pmt_in_progress->first);
858                                         break;
859                                 }
860                                 case iDVBFrontend::feCable:
861                                 {
862                                         eDVBFrontendParametersCable parm;
863                                         m_ch_current->getDVBC(parm);
864                                         snprintf(sname, 255, "%d SID 0x%02x",
865                                                 parm.frequency/1000,
866                                                 m_pmt_in_progress->first);
867                                         break;
868                                 }
869                         }
870                         SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
871                         service->m_service_name = convertDVBUTF8(sname);
872                         service->genSortName();
873                         service->m_provider_name = convertDVBUTF8(pname);
874                 }
875
876                 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
877                         SCAN_eDebug("add not scrambled!");
878                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
879                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
880                         if (i.second)
881                         {
882                                 m_last_service = i.first;
883                                 m_event(evtNewService);
884                         }
885                 }
886                 else
887                         SCAN_eDebug("dont add... is scrambled!");
888                 m_pmts_to_read.erase(m_pmt_in_progress++);
889         }
890
891         if (!m_chid_current)
892                 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
893         else
894         {
895                 addKnownGoodChannel(m_chid_current, m_ch_current);
896                 if (m_chid_current)
897                 {
898                         switch(type)
899                         {
900                                 case iDVBFrontend::feSatellite:
901                                 case iDVBFrontend::feTerrestrial:
902                                 case iDVBFrontend::feCable:
903                                 {
904                                         ePtr<iDVBFrontend> fe;
905                                         if (!m_channel->getFrontend(fe))
906                                         {
907                                                 ePyObject tp_dict = PyDict_New();
908                                                 fe->getTransponderData(tp_dict, false);
909 //                                              eDebug("add tuner data for tsid %04x, onid %04x, ns %08x",
910 //                                                      m_chid_current.transport_stream_id.get(), m_chid_current.original_network_id.get(),
911 //                                                      m_chid_current.dvbnamespace.get());
912                                                 m_tuner_data.insert(std::pair<eDVBChannelID, ePyObjectWrapper>(m_chid_current, tp_dict));
913                                                 Py_DECREF(tp_dict);
914                                         }
915                                 }
916                                 default:
917                                         break;
918                         }
919                 }
920         }
921
922         m_ch_scanned.push_back(m_ch_current);
923
924         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
925         {
926                 if (sameChannel(*i, m_ch_current))
927                 {
928                         SCAN_eDebug("remove dupe 2");
929                         m_ch_toScan.erase(i++);
930                         continue;
931                 }
932                 ++i;
933         }
934         
935         nextChannel();
936 }
937
938 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
939 {
940         m_flags = flags;
941         m_ch_toScan.clear();
942         m_ch_scanned.clear();
943         m_ch_unavailable.clear();
944         m_new_channels.clear();
945         m_tuner_data.clear();
946         m_new_services.clear();
947         m_last_service = m_new_services.end();
948
949         for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
950         {
951                 bool exist=false;
952                 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
953                 {
954                         if (sameChannel(*i, *ii, true))
955                         {
956                                 exist=true;
957                                 break;
958                         }
959                 }
960                 if (!exist)
961                         m_ch_toScan.push_back(*i);
962         }
963
964         nextChannel();
965 }
966
967 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
968 {
969         if (m_flags & scanRemoveServices)
970         {
971                 bool clearTerrestrial=false;
972                 bool clearCable=false;
973                 std::set<unsigned int> scanned_sat_positions;
974                 
975                 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
976                 for (;it != m_ch_scanned.end(); ++it)
977                 {
978                         if (m_flags & scanDontRemoveUnscanned)
979                                 db->removeServices(&(*(*it)));
980                         else
981                         {
982                                 int system;
983                                 (*it)->getSystem(system);
984                                 switch(system)
985                                 {
986                                         case iDVBFrontend::feSatellite:
987                                         {
988                                                 eDVBFrontendParametersSatellite sat_parm;
989                                                 (*it)->getDVBS(sat_parm);
990                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
991                                                 break;
992                                         }
993                                         case iDVBFrontend::feTerrestrial:
994                                         {
995                                                 clearTerrestrial=true;
996                                                 break;
997                                         }
998                                         case iDVBFrontend::feCable:
999                                         {
1000                                                 clearCable=true;
1001                                                 break;
1002                                         }
1003                                 }
1004                         }
1005                 }
1006
1007                 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
1008                 {
1009                         if (m_flags & scanDontRemoveUnscanned)
1010                                 db->removeServices(&(*(*it)));
1011                         else
1012                         {
1013                                 int system;
1014                                 (*it)->getSystem(system);
1015                                 switch(system)
1016                                 {
1017                                         case iDVBFrontend::feSatellite:
1018                                         {
1019                                                 eDVBFrontendParametersSatellite sat_parm;
1020                                                 (*it)->getDVBS(sat_parm);
1021                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
1022                                                 break;
1023                                         }
1024                                         case iDVBFrontend::feTerrestrial:
1025                                         {
1026                                                 clearTerrestrial=true;
1027                                                 break;
1028                                         }
1029                                         case iDVBFrontend::feCable:
1030                                         {
1031                                                 clearCable=true;
1032                                                 break;
1033                                         }
1034                                 }
1035                         }
1036                 }
1037
1038                 if (clearTerrestrial)
1039                 {
1040                         eDVBChannelID chid;
1041                         chid.dvbnamespace=0xEEEE0000;
1042                         db->removeServices(chid);
1043                 }
1044                 if (clearCable)
1045                 {
1046                         eDVBChannelID chid;
1047                         chid.dvbnamespace=0xFFFF0000;
1048                         db->removeServices(chid);
1049                 }
1050                 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
1051                 {
1052                         eDVBChannelID chid;
1053                         if (m_flags & scanDontRemoveFeeds)
1054                                 chid.dvbnamespace = eDVBNamespace((*x)<<16);
1055 //                      eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
1056                         db->removeServices(chid, *x);
1057                 }
1058         }
1059
1060         for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator 
1061                         ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
1062         {
1063                 int system;
1064                 ch->second->getSystem(system);
1065                 std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
1066
1067                 switch(system)
1068                 {
1069                         case iDVBFrontend::feTerrestrial:
1070                         {
1071                                 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
1072                                 eDVBFrontendParametersTerrestrial parm;
1073                                 int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
1074                                 p->getDVBT(parm);
1075 //                              eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
1076 //                                      ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
1077 //                                      ch->first.dvbnamespace.get(), freq, parm.frequency);
1078                                 parm.frequency = freq;
1079                                 p->setDVBT(parm);
1080                                 break;
1081                         }
1082                         case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
1083                         case iDVBFrontend::feCable:
1084                                 break;
1085                 }
1086
1087                 if (m_flags & scanOnlyFree)
1088                 {
1089                         eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
1090                         ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
1091                 }
1092
1093                 db->addChannelToList(ch->first, ch->second);
1094         }
1095
1096         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
1097                 service(m_new_services.begin()); service != m_new_services.end(); ++service)
1098         {
1099                 ePtr<eDVBService> dvb_service;
1100                 if (!db->getService(service->first, dvb_service))
1101                 {
1102                         if (dvb_service->m_flags & eDVBService::dxNoSDT)
1103                                 continue;
1104                         if (!(dvb_service->m_flags & eDVBService::dxHoldName))
1105                         {
1106                                 dvb_service->m_service_name = service->second->m_service_name;
1107                                 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
1108                         }
1109                         dvb_service->m_provider_name = service->second->m_provider_name;
1110                         if (service->second->m_ca.size())
1111                                 dvb_service->m_ca = service->second->m_ca;
1112                         if (!dontRemoveOldFlags) // do not remove new found flags when not wished
1113                                 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1114                 }
1115                 else
1116                 {
1117                         db->addService(service->first, service->second);
1118                         if (!(m_flags & scanRemoveServices))
1119                                 service->second->m_flags |= eDVBService::dxNewFound;
1120                 }
1121         }
1122 }
1123
1124 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1125 {
1126         const ServiceDescriptionList &services = *sdt.getDescriptions();
1127         SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1128         eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1129         
1130         /* save correct CHID for this channel */
1131         m_chid_current = chid;
1132
1133         for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1134         {
1135                 unsigned short service_id = (*s)->getServiceId();
1136                 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1137                 bool add = true;
1138
1139                 if (m_flags & scanOnlyFree)
1140                 {
1141                         std::map<unsigned short, service>::iterator it =
1142                                 m_pmts_to_read.find(service_id);
1143                         if (it != m_pmts_to_read.end())
1144                         {
1145                                 if (it->second.scrambled)
1146                                 {
1147                                         SCAN_eDebug("is scrambled!");
1148                                         add = false;
1149                                 }
1150                                 else
1151                                         SCAN_eDebug("is free");
1152                         }
1153                         else {
1154                                 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1155                                 add = false;
1156                         }
1157                 }
1158
1159                 if (add)
1160                 {
1161                         eServiceReferenceDVB ref;
1162                         ePtr<eDVBService> service = new eDVBService;
1163
1164                         ref.set(chid);
1165                         ref.setServiceID(service_id);
1166
1167                         for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1168                                         desc != (*s)->getDescriptors()->end(); ++desc)
1169                         {
1170                                 switch ((*desc)->getTag())
1171                                 {
1172                                 case SERVICE_DESCRIPTOR:
1173                                 {
1174                                         ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1175                                         ref.setServiceType(d.getServiceType());
1176                                         service->m_service_name = convertDVBUTF8(d.getServiceName());
1177                                         service->genSortName();
1178
1179                                         service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1180                                         SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1181                                         break;
1182                                 }
1183                                 case CA_IDENTIFIER_DESCRIPTOR:
1184                                 {
1185                                         CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1186                                         const CaSystemIdList &caids = *d.getCaSystemIds();
1187                                         SCAN_eDebugNoNewLine("CA ");
1188                                         for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1189                                         {
1190                                                 SCAN_eDebugNoNewLine("%04x ", *i);
1191                                                 service->m_ca.push_front(*i);
1192                                         }
1193                                         SCAN_eDebug("");
1194                                         break;
1195                                 }
1196                                 default:
1197                                         SCAN_eDebug("descr<%x>", (*desc)->getTag());
1198                                         break;
1199                                 }
1200                         }
1201
1202                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1203                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1204
1205                         if (i.second)
1206                         {
1207                                 m_last_service = i.first;
1208                                 m_event(evtNewService);
1209                         }
1210                 }
1211                 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1212                         m_abort_current_pmt = true;
1213                 else
1214                         m_pmts_to_read.erase(service_id);
1215         }
1216
1217         return 0;
1218 }
1219
1220 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1221 {
1222         connection = new eConnection(this, m_event.connect(event));
1223         return 0;
1224 }
1225
1226 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1227 {
1228         transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1229         transponders_total = m_ch_toScan.size() + transponders_done;
1230         services = m_new_services.size();
1231 }
1232
1233 void eDVBScan::getLastServiceName(std::string &last_service_name)
1234 {
1235         if (m_last_service == m_new_services.end())
1236                 last_service_name = "";
1237         else
1238                 last_service_name = m_last_service->second->m_service_name;
1239 }
1240
1241 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1242 {
1243         if (m_channel)
1244                 return m_channel->getFrontend(fe);
1245         fe = 0;
1246         return -1;
1247 }
1248
1249 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)
1250 {
1251         if (m_ch_current)
1252         {
1253                 tp = m_ch_current;
1254                 return 0;
1255         }
1256         tp = 0;
1257         return -1;
1258 }