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