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