dont clear when not needed
[vuplus_dvbapp] / lib / dvb / scan.cpp
1 #include <lib/dvb/idvb.h>
2 #include <dvbsi++/descriptor_tag.h>
3 #include <dvbsi++/service_descriptor.h>
4 #include <dvbsi++/satellite_delivery_system_descriptor.h>
5 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
6 #include <dvbsi++/cable_delivery_system_descriptor.h>
7 #include <dvbsi++/ca_identifier_descriptor.h>
8 #include <dvbsi++/registration_descriptor.h>
9 #include <lib/dvb/specs.h>
10 #include <lib/dvb/esection.h>
11 #include <lib/dvb/scan.h>
12 #include <lib/dvb/frontend.h>
13 #include <lib/base/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         int type;
710         if (m_ch_current->getSystem(type))
711                 type = -1;
712
713         for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
714         {
715                 eServiceReferenceDVB ref;
716                 ePtr<eDVBService> service = new eDVBService;
717
718                 if (!m_chid_current)
719                 {
720                         unsigned long hash = 0;
721
722                         m_ch_current->getHash(hash);
723
724                         m_chid_current = eDVBChannelID(
725                                 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
726                                 m_pat_tsid, eOriginalNetworkID(0));
727                 }
728
729                 if (m_pmt_in_progress->second.serviceType == 1)
730                         SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
731                 else if (m_pmt_in_progress->second.serviceType == 2)
732                         SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
733                 else
734                         SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
735
736                 ref.set(m_chid_current);
737                 ref.setServiceID(m_pmt_in_progress->first);
738                 ref.setServiceType(m_pmt_in_progress->second.serviceType);
739
740                 if (type != -1)
741                 {
742                         char sname[255];
743                         char pname[255];
744                         memset(pname, 0, sizeof(pname));
745                         memset(sname, 0, sizeof(sname));
746                         switch(type)
747                         {
748                                 case iDVBFrontend::feSatellite:
749                                 {
750                                         eDVBFrontendParametersSatellite parm;
751                                         m_ch_current->getDVBS(parm);
752                                         snprintf(sname, 255, "%d%c SID 0x%02x",
753                                                         parm.frequency/1000,
754                                                         parm.polarisation ? 'V' : 'H',
755                                                         m_pmt_in_progress->first);
756                                         snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
757                                                 parm.system ? "DVB-S2" : "DVB-S",
758                                                 parm.modulation == 1 ? "QPSK" : "8PSK",
759                                                 parm.frequency/1000,
760                                                 parm.polarisation ? 'V' : 'H',
761                                                 parm.orbital_position/10,
762                                                 parm.orbital_position%10,
763                                                 parm.orbital_position > 0 ? 'E' : 'W');
764                                         break;
765                                 }
766                                 case iDVBFrontend::feTerrestrial:
767                                 {
768                                         eDVBFrontendParametersTerrestrial parm;
769                                         m_ch_current->getDVBT(parm);
770                                         snprintf(sname, 255, "%d SID 0x%02x",
771                                                 parm.frequency/1000,
772                                                 m_pmt_in_progress->first);
773                                         break;
774                                 }
775                                 case iDVBFrontend::feCable:
776                                 {
777                                         eDVBFrontendParametersCable parm;
778                                         m_ch_current->getDVBC(parm);
779                                         snprintf(sname, 255, "%d SID 0x%02x",
780                                                 parm.frequency/1000,
781                                                 m_pmt_in_progress->first);
782                                         break;
783                                 }
784                         }
785                         SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
786                         service->m_service_name = convertDVBUTF8(sname);
787                         service->genSortName();
788                         service->m_provider_name = convertDVBUTF8(pname);
789                 }
790
791                 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
792                         SCAN_eDebug("add not scrambled!");
793                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
794                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
795                         if (i.second)
796                         {
797                                 m_last_service = i.first;
798                                 m_event(evtNewService);
799                         }
800                 }
801                 else
802                         SCAN_eDebug("dont add... is scrambled!");
803                 m_pmts_to_read.erase(m_pmt_in_progress++);
804         }
805
806         if (!m_chid_current)
807                 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
808         else
809         {
810                 addKnownGoodChannel(m_chid_current, m_ch_current);
811                 if (m_chid_current)
812                 {
813                         switch(type)
814                         {
815                                 case iDVBFrontend::feSatellite:
816                                 case iDVBFrontend::feTerrestrial:
817                                 case iDVBFrontend::feCable:
818                                 {
819                                         ePtr<iDVBFrontend> fe;
820                                         if (!m_channel->getFrontend(fe))
821                                         {
822                                                 ePyObject tp_dict = PyDict_New();
823                                                 fe->getTransponderData(tp_dict, false);
824 //                                              eDebug("add tuner data for tsid %04x, onid %04x, ns %08x",
825 //                                                      m_chid_current.transport_stream_id.get(), m_chid_current.original_network_id.get(),
826 //                                                      m_chid_current.dvbnamespace.get());
827                                                 m_tuner_data.insert(std::pair<eDVBChannelID, ePyObjectWrapper>(m_chid_current, tp_dict));
828                                                 Py_DECREF(tp_dict);
829                                         }
830                                 }
831                                 default:
832                                         break;
833                         }
834                 }
835         }
836
837         m_ch_scanned.push_back(m_ch_current);
838
839         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
840         {
841                 if (sameChannel(*i, m_ch_current))
842                 {
843                         SCAN_eDebug("remove dupe 2");
844                         m_ch_toScan.erase(i++);
845                         continue;
846                 }
847                 ++i;
848         }
849         
850         nextChannel();
851 }
852
853 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
854 {
855         m_flags = flags;
856         m_ch_toScan.clear();
857         m_ch_scanned.clear();
858         m_ch_unavailable.clear();
859         m_new_channels.clear();
860         m_tuner_data.clear();
861         m_new_services.clear();
862         m_last_service = m_new_services.end();
863
864         for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
865         {
866                 bool exist=false;
867                 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
868                 {
869                         if (sameChannel(*i, *ii, true))
870                         {
871                                 exist=true;
872                                 break;
873                         }
874                 }
875                 if (!exist)
876                         m_ch_toScan.push_back(*i);
877         }
878
879         nextChannel();
880 }
881
882 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
883 {
884         if (m_flags & scanRemoveServices)
885         {
886                 bool clearTerrestrial=false;
887                 bool clearCable=false;
888                 std::set<unsigned int> scanned_sat_positions;
889                 
890                 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
891                 for (;it != m_ch_scanned.end(); ++it)
892                 {
893                         if (m_flags & scanDontRemoveUnscanned)
894                                 db->removeServices(&(*(*it)));
895                         else
896                         {
897                                 int system;
898                                 (*it)->getSystem(system);
899                                 switch(system)
900                                 {
901                                         case iDVBFrontend::feSatellite:
902                                         {
903                                                 eDVBFrontendParametersSatellite sat_parm;
904                                                 (*it)->getDVBS(sat_parm);
905                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
906                                                 break;
907                                         }
908                                         case iDVBFrontend::feTerrestrial:
909                                         {
910                                                 clearTerrestrial=true;
911                                                 break;
912                                         }
913                                         case iDVBFrontend::feCable:
914                                         {
915                                                 clearCable=true;
916                                                 break;
917                                         }
918                                 }
919                         }
920                 }
921
922                 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
923                 {
924                         if (m_flags & scanDontRemoveUnscanned)
925                                 db->removeServices(&(*(*it)));
926                         else
927                         {
928                                 int system;
929                                 (*it)->getSystem(system);
930                                 switch(system)
931                                 {
932                                         case iDVBFrontend::feSatellite:
933                                         {
934                                                 eDVBFrontendParametersSatellite sat_parm;
935                                                 (*it)->getDVBS(sat_parm);
936                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
937                                                 break;
938                                         }
939                                         case iDVBFrontend::feTerrestrial:
940                                         {
941                                                 clearTerrestrial=true;
942                                                 break;
943                                         }
944                                         case iDVBFrontend::feCable:
945                                         {
946                                                 clearCable=true;
947                                                 break;
948                                         }
949                                 }
950                         }
951                 }
952
953                 if (clearTerrestrial)
954                 {
955                         eDVBChannelID chid;
956                         chid.dvbnamespace=0xEEEE0000;
957                         db->removeServices(chid);
958                 }
959                 if (clearCable)
960                 {
961                         eDVBChannelID chid;
962                         chid.dvbnamespace=0xFFFF0000;
963                         db->removeServices(chid);
964                 }
965                 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
966                 {
967                         eDVBChannelID chid;
968                         if (m_flags & scanDontRemoveFeeds)
969                                 chid.dvbnamespace = eDVBNamespace((*x)<<16);
970 //                      eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
971                         db->removeServices(chid, *x);
972                 }
973         }
974
975         for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator 
976                         ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
977         {
978                 int system;
979                 ch->second->getSystem(system);
980                 std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
981
982                 switch(system)
983                 {
984                         case iDVBFrontend::feTerrestrial:
985                         {
986                                 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
987                                 eDVBFrontendParametersTerrestrial parm;
988                                 int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
989                                 p->getDVBT(parm);
990 //                              eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
991 //                                      ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
992 //                                      ch->first.dvbnamespace.get(), freq, parm.frequency);
993                                 parm.frequency = freq;
994                                 p->setDVBT(parm);
995                                 break;
996                         }
997                         case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
998                         case iDVBFrontend::feCable:
999                                 break;
1000                 }
1001
1002                 if (m_flags & scanOnlyFree)
1003                 {
1004                         eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
1005                         ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
1006                 }
1007
1008                 db->addChannelToList(ch->first, ch->second);
1009         }
1010
1011         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
1012                 service(m_new_services.begin()); service != m_new_services.end(); ++service)
1013         {
1014                 ePtr<eDVBService> dvb_service;
1015                 if (!db->getService(service->first, dvb_service))
1016                 {
1017                         if (dvb_service->m_flags & eDVBService::dxNoSDT)
1018                                 continue;
1019                         if (!(dvb_service->m_flags & eDVBService::dxHoldName))
1020                         {
1021                                 dvb_service->m_service_name = service->second->m_service_name;
1022                                 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
1023                         }
1024                         dvb_service->m_provider_name = service->second->m_provider_name;
1025                         if (service->second->m_ca.size())
1026                                 dvb_service->m_ca = service->second->m_ca;
1027                         if (!dontRemoveOldFlags) // do not remove new found flags when not wished
1028                                 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1029                 }
1030                 else
1031                 {
1032                         db->addService(service->first, service->second);
1033                         if (!(m_flags & scanRemoveServices))
1034                                 service->second->m_flags |= eDVBService::dxNewFound;
1035                 }
1036         }
1037 }
1038
1039 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1040 {
1041         const ServiceDescriptionList &services = *sdt.getDescriptions();
1042         SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1043         eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1044         
1045         /* save correct CHID for this channel */
1046         m_chid_current = chid;
1047
1048         for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1049         {
1050                 unsigned short service_id = (*s)->getServiceId();
1051                 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1052                 bool add = true;
1053
1054                 if (m_flags & scanOnlyFree)
1055                 {
1056                         std::map<unsigned short, service>::iterator it =
1057                                 m_pmts_to_read.find(service_id);
1058                         if (it != m_pmts_to_read.end())
1059                         {
1060                                 if (it->second.scrambled)
1061                                 {
1062                                         SCAN_eDebug("is scrambled!");
1063                                         add = false;
1064                                 }
1065                                 else
1066                                         SCAN_eDebug("is free");
1067                         }
1068                         else {
1069                                 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1070                                 add = false;
1071                         }
1072                 }
1073
1074                 if (add)
1075                 {
1076                         eServiceReferenceDVB ref;
1077                         ePtr<eDVBService> service = new eDVBService;
1078
1079                         ref.set(chid);
1080                         ref.setServiceID(service_id);
1081
1082                         for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1083                                         desc != (*s)->getDescriptors()->end(); ++desc)
1084                         {
1085                                 switch ((*desc)->getTag())
1086                                 {
1087                                 case SERVICE_DESCRIPTOR:
1088                                 {
1089                                         ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1090                                         ref.setServiceType(d.getServiceType());
1091                                         service->m_service_name = convertDVBUTF8(d.getServiceName());
1092                                         service->genSortName();
1093
1094                                         service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1095                                         SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1096                                         break;
1097                                 }
1098                                 case CA_IDENTIFIER_DESCRIPTOR:
1099                                 {
1100                                         CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1101                                         const CaSystemIdList &caids = *d.getCaSystemIds();
1102                                         SCAN_eDebugNoNewLine("CA ");
1103                                         for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1104                                         {
1105                                                 SCAN_eDebugNoNewLine("%04x ", *i);
1106                                                 service->m_ca.push_front(*i);
1107                                         }
1108                                         SCAN_eDebug("");
1109                                         break;
1110                                 }
1111                                 default:
1112                                         SCAN_eDebug("descr<%x>", (*desc)->getTag());
1113                                         break;
1114                                 }
1115                         }
1116
1117                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1118                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1119
1120                         if (i.second)
1121                         {
1122                                 m_last_service = i.first;
1123                                 m_event(evtNewService);
1124                         }
1125                 }
1126                 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1127                         m_abort_current_pmt = true;
1128                 else
1129                         m_pmts_to_read.erase(service_id);
1130         }
1131
1132         return 0;
1133 }
1134
1135 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1136 {
1137         connection = new eConnection(this, m_event.connect(event));
1138         return 0;
1139 }
1140
1141 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1142 {
1143         transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1144         transponders_total = m_ch_toScan.size() + transponders_done;
1145         services = m_new_services.size();
1146 }
1147
1148 void eDVBScan::getLastServiceName(std::string &last_service_name)
1149 {
1150         if (m_last_service == m_new_services.end())
1151                 last_service_name = "";
1152         else
1153                 last_service_name = m_last_service->second->m_service_name;
1154 }
1155
1156 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1157 {
1158         if (m_channel)
1159                 return m_channel->getFrontend(fe);
1160         fe = 0;
1161         return -1;
1162 }
1163
1164 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)
1165 {
1166         if (m_ch_current)
1167         {
1168                 tp = m_ch_current;
1169                 return 0;
1170         }
1171         tp = 0;
1172         return -1;
1173 }