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