some service scan improovements
[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(-1);
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                                 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                                                 switch ((*desc)->getTag())
303                                                 {
304                                                 case DTS_DESCRIPTOR:
305                                                 case AAC_DESCRIPTOR:
306                                                         isaudio = 1;
307                                                 case AC3_DESCRIPTOR:
308                                                         isaudio = 1;
309                                                         break;
310                                                 case CA_DESCRIPTOR:
311                                                         is_scrambled = 1;
312                                                         break;
313                                                 case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
314                                                 {
315                                                                 /* libdvbsi++ doesn't yet support this descriptor type, so work around. */
316                                                         if ((*desc)->getLength() != 4)
317                                                                 break;
318                                                         unsigned char descr[6];
319                                                         (*desc)->writeToBuffer(descr);
320                                                         int format_identifier = (descr[2] << 24) | (descr[3] << 16) | (descr[4] << 8) | (descr[5]);
321                                                         switch (format_identifier)
322                                                         {
323                                                         case 0x41432d33:
324                                                                 isaudio = 1;
325                                                         default:
326                                                                 break;
327                                                         }
328                                                         break;
329                                                 }
330                                                 }
331                                         }
332                                         break;
333                                 }
334                                 if (isaudio)
335                                         have_audio = true;
336                                 else if (isvideo)
337                                         have_video = true;
338                                 else
339                                         continue;
340                                 if (is_scrambled)
341                                         scrambled = true;
342                         }
343                         for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
344                                 desc != pmt.getDescriptors()->end(); ++desc)
345                         {
346                                 if ((*desc)->getTag() == CA_DESCRIPTOR)
347                                         scrambled = true;
348                         }
349                 }
350                 m_pmt_in_progress->second.scrambled = scrambled;
351                 if ( have_video )
352                         m_pmt_in_progress->second.serviceType = 1;
353                 else if ( have_audio )
354                         m_pmt_in_progress->second.serviceType = 2;
355                 else
356                         m_pmt_in_progress->second.serviceType = 100;
357         }
358         if (err == -2) // aborted in sdt progress
359                 m_pmts_to_read.erase(m_pmt_in_progress++);
360         else if (m_pmt_running)
361                 ++m_pmt_in_progress;
362         else
363         {
364                 m_pmt_in_progress = m_pmts_to_read.begin();
365                 m_pmt_running = true;
366         }
367
368         if (m_pmt_in_progress != m_pmts_to_read.end())
369                 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first));
370         else
371         {
372                 m_pmt_running = false;
373                 channelDone();
374         }
375 }
376
377
378 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
379 {
380                 /* add it to the list of known channels. */
381         if (chid)
382                 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
383 }
384
385 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
386 {
387                 /* check if we don't already have that channel ... */
388
389         int type;
390         feparm->getSystem(type);
391
392         switch(type)
393         {
394         case iDVBFrontend::feSatellite:
395         {
396                 eDVBFrontendParametersSatellite parm;
397                 feparm->getDVBS(parm);
398                 eDebug("try to add %d %d %d %d %d %d",
399                         parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
400                 break;
401         }
402         case iDVBFrontend::feCable:
403         {
404                 eDVBFrontendParametersCable parm;
405                 feparm->getDVBC(parm);
406                 eDebug("try to add %d %d %d %d",
407                         parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
408                 break;
409         }
410         case iDVBFrontend::feTerrestrial:
411         {
412                 eDVBFrontendParametersTerrestrial parm;
413                 feparm->getDVBT(parm);
414                 eDebug("try to add %d %d %d %d %d %d %d %d",
415                         parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
416                         parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
417                 break;
418         }
419         }
420
421         int found_count=0;
422                 /* ... in the list of channels to scan */
423         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
424         {
425                 if (sameChannel(*i, feparm))
426                 {
427                         if (!found_count)
428                         {
429                                 *i = feparm;  // update
430                                 eDebug("update");
431                         }
432                         else
433                         {
434                                 eDebug("remove dupe");
435                                 m_ch_toScan.erase(i++);
436                                 continue;
437                         }
438                         ++found_count;
439                 }
440                 ++i;
441         }
442
443         if (found_count > 0)
444         {
445                 eDebug("already in todo list");
446                 return;
447         }
448
449                 /* ... in the list of successfully scanned channels */
450         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
451                 if (sameChannel(*i, feparm))
452                 {
453                         eDebug("successfully scanned");
454                         return;
455                 }
456
457                 /* ... in the list of unavailable channels */
458         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
459                 if (sameChannel(*i, feparm, true))
460                 {
461                         eDebug("scanned but not available");
462                         return;
463                 }
464
465                 /* ... on the current channel */
466         if (sameChannel(m_ch_current, feparm))
467         {
468                 eDebug("is current");
469                 return;
470         }
471
472         eDebug("really add");
473                 /* otherwise, add it to the todo list. */
474         m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
475 }
476
477 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
478 {
479         int diff;
480         if (ch1->calculateDifference(ch2, diff, exact))
481                 return 0;
482         if (diff < 4000) // more than 4mhz difference?
483                 return 1;
484         return 0;
485 }
486
487 void eDVBScan::channelDone()
488 {
489         if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
490         {
491                 unsigned long hash = 0;
492
493                 // m_ch_current is not set, when eDVBScan is just used for a SDT update
494                 if (!m_ch_current)
495                 {
496                         unsigned int channelFlags;
497                         m_channel->getCurrentFrontendParameters(m_ch_current);
498                         m_ch_current->getFlags(channelFlags);
499                         if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
500                                 m_flags |= scanOnlyFree;
501                 }
502
503                 m_ch_current->getHash(hash);
504                 
505                 eDVBNamespace dvbnamespace = buildNamespace(
506                         (**m_SDT->getSections().begin()).getOriginalNetworkId(),
507                         (**m_SDT->getSections().begin()).getTransportStreamId(),
508                         hash);
509                 
510                 SCAN_eDebug("SDT: ");
511                 std::vector<ServiceDescriptionSection*>::const_iterator i;
512                 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
513                         processSDT(dvbnamespace, **i);
514                 m_ready &= ~validSDT;
515         }
516         
517         if (m_ready & validNIT)
518         {
519                 eDebug("validNIT");
520                 int system;
521                 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
522                 m_ch_current->getSystem(system);
523                 SCAN_eDebug("dumping NIT");
524                 if (m_flags & clearToScanOnFirstNIT)
525                 {
526                         m_ch_toScan_backup = m_ch_toScan;
527                         m_ch_toScan.clear();
528                 }
529                 std::vector<NetworkInformationSection*>::const_iterator i;
530                 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
531                 {
532                         const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
533                         
534                         for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin()); 
535                                 tsinfo != tsinfovec.end(); ++tsinfo)
536                         {
537                                 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
538                                         (*tsinfo)->getOriginalNetworkId());
539                                 
540                                 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
541                                 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
542                                 
543                                 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
544                                                 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
545                                 {
546                                         switch ((*desc)->getTag())
547                                         {
548                                         case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
549                                         {
550                                                 if (system != iDVBFrontend::feCable)
551                                                         break; // when current locked transponder is no cable transponder ignore this descriptor
552                                                 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
553                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
554                                                 eDVBFrontendParametersCable cable;
555                                                 cable.set(d);
556                                                 feparm->setDVBC(cable);
557
558                                                 unsigned long hash=0;
559                                                 feparm->getHash(hash);
560                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
561
562                                                 addChannelToScan(
563                                                         eDVBChannelID(ns, tsid, onid),
564                                                         feparm);
565                                                 break;
566                                         }
567                                         case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
568                                         {
569                                                 if (system != iDVBFrontend::feTerrestrial)
570                                                         break; // when current locked transponder is no terrestrial transponder ignore this descriptor
571                                                 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
572                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
573                                                 eDVBFrontendParametersTerrestrial terr;
574                                                 terr.set(d);
575                                                 feparm->setDVBT(terr);
576
577                                                 unsigned long hash=0;
578                                                 feparm->getHash(hash);
579                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
580
581                                                 addChannelToScan(
582                                                         eDVBChannelID(ns, tsid, onid),
583                                                         feparm);
584                                                 break;
585                                         }
586                                         case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
587                                         {
588                                                 if (system != iDVBFrontend::feSatellite)
589                                                         break; // when current locked transponder is no satellite transponder ignore this descriptor
590
591                                                 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
592                                                 if (d.getFrequency() < 10000)
593                                                         break;
594                                                 
595                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
596                                                 eDVBFrontendParametersSatellite sat;
597                                                 sat.set(d);
598
599                                                 eDVBFrontendParametersSatellite p;
600                                                 m_ch_current->getDVBS(p);
601
602                                                 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
603                                                         sat.orbital_position = p.orbital_position;
604
605                                                 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
606                                                 {
607                                                         eDebug("found transponder with incorrect west/east flag ... correct this");
608                                                         sat.orbital_position = p.orbital_position;
609                                                 }
610
611                                                 feparm->setDVBS(sat);
612
613                                                 if ( p.orbital_position != sat.orbital_position)
614                                                         SCAN_eDebug("dropping this transponder, it's on another satellite.");
615                                                 else
616                                                 {
617                                                         unsigned long hash=0;
618                                                         feparm->getHash(hash);
619                                                         addChannelToScan(
620                                                                         eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
621                                                                         feparm);
622                                                 }
623                                                 break;
624                                         }
625                                         default:
626                                                 SCAN_eDebug("descr<%x>", (*desc)->getTag());
627                                                 break;
628                                         }
629                                 }
630                         }
631                         
632                 }
633
634                         /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
635                            no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
636                            has been found.
637
638                            This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
639                         */
640                 if (m_flags & clearToScanOnFirstNIT)
641                 {
642                         if (m_ch_toScan.empty())
643                         {
644                                 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
645                                 m_ch_toScan = m_ch_toScan_backup;
646                         } else
647                                 m_flags &= ~clearToScanOnFirstNIT;
648                 }
649                 m_ready &= ~validNIT;
650         }
651
652         if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
653         {
654                 if (m_abort_current_pmt)
655                 {
656                         m_abort_current_pmt = false;
657                         PMTready(-1);
658                 }
659                 return;
660         }
661
662         SCAN_eDebug("channel done!");
663         
664                 /* if we had services on this channel, we declare
665                    this channels as "known good". add it.
666                    
667                    (TODO: not yet implemented)
668                    a NIT entry could have possible overridden
669                    our frontend data with more exact data.
670                    
671                    (TODO: not yet implemented)
672                    the tuning process could have lead to more
673                    exact data than the user entered.
674                    
675                    The channel id was probably corrected
676                    by the data written in the SDT. this is
677                    important, as "initial transponder lists"
678                    usually don't have valid CHIDs (and that's
679                    good).
680                    
681                    These are the reasons for adding the transponder
682                    here, and not before.
683                 */
684
685         for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
686         {
687                 int type;
688                 eServiceReferenceDVB ref;
689                 ePtr<eDVBService> service = new eDVBService;
690
691                 if (!m_chid_current)
692                 {
693                         unsigned long hash = 0;
694
695                         // m_ch_current is not set, when eDVBScan is just used for a SDT update
696                         if (!m_ch_current)
697                         {
698                                 unsigned int channelFlags;
699                                 m_channel->getCurrentFrontendParameters(m_ch_current);
700                                 m_ch_current->getFlags(channelFlags);
701                                 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
702                                         m_flags |= scanOnlyFree;
703                         }
704
705                         m_ch_current->getHash(hash);
706
707                         m_chid_current = eDVBChannelID(
708                                 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
709                                 m_pat_tsid, eOriginalNetworkID(0));
710                 }
711
712                 if (m_pmt_in_progress->second.serviceType == 1)
713                         SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
714                 else if (m_pmt_in_progress->second.serviceType == 2)
715                         SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
716                 else
717                         SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
718
719                 ref.set(m_chid_current);
720                 ref.setServiceID(m_pmt_in_progress->first);
721                 ref.setServiceType(m_pmt_in_progress->second.serviceType);
722
723                 if (!m_ch_current->getSystem(type))
724                 {
725                         char sname[255];
726                         char pname[255];
727                         memset(pname, 0, sizeof(pname));
728                         memset(sname, 0, sizeof(sname));
729                         switch(type)
730                         {
731                                 case iDVBFrontend::feSatellite:
732                                 {
733                                         eDVBFrontendParametersSatellite parm;
734                                         m_ch_current->getDVBS(parm);
735                                         snprintf(sname, 255, "%d%c SID 0x%02x",
736                                                         parm.frequency/1000,
737                                                         parm.polarisation ? 'V' : 'H',
738                                                         m_pmt_in_progress->first);
739                                         snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
740                                                 parm.system ? "DVB-S2" : "DVB-S",
741                                                 parm.modulation == 1 ? "QPSK" : "8PSK",
742                                                 parm.frequency/1000,
743                                                 parm.polarisation ? 'V' : 'H',
744                                                 parm.orbital_position/10,
745                                                 parm.orbital_position%10,
746                                                 parm.orbital_position > 0 ? 'E' : 'W');
747                                         break;
748                                 }
749                                 case iDVBFrontend::feTerrestrial:
750                                 {
751                                         eDVBFrontendParametersTerrestrial parm;
752                                         m_ch_current->getDVBT(parm);
753                                         snprintf(sname, 255, "%d SID 0x%02x",
754                                                 parm.frequency/1000,
755                                                 m_pmt_in_progress->first);
756                                         break;
757                                 }
758                                 case iDVBFrontend::feCable:
759                                 {
760                                         eDVBFrontendParametersCable parm;
761                                         m_ch_current->getDVBC(parm);
762                                         snprintf(sname, 255, "%d SID 0x%02x",
763                                                 parm.frequency/1000,
764                                                 m_pmt_in_progress->first);
765                                         break;
766                                 }
767                         }
768                         SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
769                         service->m_service_name = convertDVBUTF8(sname);
770                         service->genSortName();
771                         service->m_provider_name = pname;
772                 }
773
774                 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
775
776                 if (i.second)
777                 {
778                         m_last_service = i.first;
779                         m_event(evtNewService);
780                 }
781                 m_pmts_to_read.erase(m_pmt_in_progress++);
782         }
783
784         if (!m_chid_current)
785                 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
786         else
787                 addKnownGoodChannel(m_chid_current, m_ch_current);
788         
789         m_ch_scanned.push_back(m_ch_current);
790         
791         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
792         {
793                 if (sameChannel(*i, m_ch_current))
794                 {
795                         eDebug("remove dupe 2");
796                         m_ch_toScan.erase(i++);
797                         continue;
798                 }
799                 ++i;
800         }
801         
802         nextChannel();
803 }
804
805 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
806 {
807         m_flags = flags;
808         m_ch_toScan.clear();
809         m_ch_scanned.clear();
810         m_ch_unavailable.clear();
811         m_new_channels.clear();
812         m_new_services.clear();
813         m_last_service = m_new_services.end();
814
815         for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
816         {
817                 bool exist=false;
818                 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
819                 {
820                         if (sameChannel(*i, *ii, true))
821                         {
822                                 exist=true;
823                                 break;
824                         }
825                 }
826                 if (!exist)
827                         m_ch_toScan.push_back(*i);
828         }
829
830         nextChannel();
831 }
832
833 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
834 {
835         if (m_flags & scanRemoveServices)
836         {
837                 bool clearTerrestrial=false;
838                 bool clearCable=false;
839                 std::set<unsigned int> scanned_sat_positions;
840                 
841                 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
842                 for (;it != m_ch_scanned.end(); ++it)
843                 {
844                         if (m_flags & scanDontRemoveUnscanned) {
845                                 eDebug("scanDontRemoveUnscanned!");
846                                 db->removeServices(&(*(*it)));
847                         }
848                         else
849                         {
850                                 int system;
851                                 (*it)->getSystem(system);
852                                 switch(system)
853                                 {
854                                         case iDVBFrontend::feSatellite:
855                                         {
856                                                 eDVBFrontendParametersSatellite sat_parm;
857                                                 (*it)->getDVBS(sat_parm);
858                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
859                                                 break;
860                                         }
861                                         case iDVBFrontend::feTerrestrial:
862                                         {
863                                                 clearTerrestrial=true;
864                                                 break;
865                                         }
866                                         case iDVBFrontend::feCable:
867                                         {
868                                                 clearCable=true;
869                                                 break;
870                                         }
871                                 }
872                         }
873                 }
874
875                 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
876                 {
877                         if (m_flags & scanDontRemoveUnscanned)
878                                 db->removeServices(&(*(*it)));
879                         else
880                         {
881                                 int system;
882                                 (*it)->getSystem(system);
883                                 switch(system)
884                                 {
885                                         case iDVBFrontend::feSatellite:
886                                         {
887                                                 eDVBFrontendParametersSatellite sat_parm;
888                                                 (*it)->getDVBS(sat_parm);
889                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
890                                                 break;
891                                         }
892                                         case iDVBFrontend::feTerrestrial:
893                                         {
894                                                 clearTerrestrial=true;
895                                                 break;
896                                         }
897                                         case iDVBFrontend::feCable:
898                                         {
899                                                 clearCable=true;
900                                                 break;
901                                         }
902                                 }
903                         }
904                 }
905
906                 if (clearTerrestrial)
907                 {
908                         eDVBChannelID chid;
909                         chid.dvbnamespace=0xEEEE0000;
910                         db->removeServices(chid);
911                 }
912                 if (clearCable)
913                 {
914                         eDVBChannelID chid;
915                         chid.dvbnamespace=0xFFFF0000;
916                         db->removeServices(chid);
917                 }
918                 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
919                 {
920                         eDVBChannelID chid;
921                         if (m_flags & scanDontRemoveFeeds)
922                                 chid.dvbnamespace = eDVBNamespace((*x)<<16);
923 //                      eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
924                         db->removeServices(chid, *x);
925                 }
926         }
927
928         for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator 
929                         ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
930         {
931                 if (m_flags & scanOnlyFree)
932                 {
933                         eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
934                         ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
935                 }
936                 db->addChannelToList(ch->first, ch->second);
937         }
938
939         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
940                 service(m_new_services.begin()); service != m_new_services.end(); ++service)
941         {
942                 ePtr<eDVBService> dvb_service;
943                 if (!db->getService(service->first, dvb_service))
944                 {
945                         if (dvb_service->m_flags & eDVBService::dxNoSDT)
946                                 continue;
947                         if (!(dvb_service->m_flags & eDVBService::dxHoldName))
948                         {
949                                 dvb_service->m_service_name = service->second->m_service_name;
950                                 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
951                         }
952                         dvb_service->m_provider_name = service->second->m_provider_name;
953                         if (service->second->m_ca.size())
954                                 dvb_service->m_ca = service->second->m_ca;
955                         if (!dontRemoveOldFlags) // do not remove new found flags when not wished
956                                 dvb_service->m_flags &= ~eDVBService::dxNewFound;
957                 }
958                 else
959                 {
960                         db->addService(service->first, service->second);
961                         if (!(m_flags & scanRemoveServices))
962                                 service->second->m_flags |= eDVBService::dxNewFound;
963                 }
964         }
965 }
966
967 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
968 {
969         const ServiceDescriptionList &services = *sdt.getDescriptions();
970         SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
971         eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
972         
973         /* save correct CHID for this channel */
974         m_chid_current = chid;
975
976         for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
977         {
978                 unsigned short service_id = (*s)->getServiceId();
979                 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
980                 bool add = true;
981
982                 if (m_flags & scanOnlyFree)
983                 {
984                         std::map<unsigned short, service>::iterator it =
985                                 m_pmts_to_read.find(service_id);
986                         if (it != m_pmts_to_read.end())
987                         {
988                                 if (it->second.scrambled)
989                                 {
990                                         SCAN_eDebug("is scrambled!");
991                                         add = false;
992                                 }
993                         }
994                         else
995                                 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
996                 }
997
998                 if (add)
999                 {
1000                         eServiceReferenceDVB ref;
1001                         ePtr<eDVBService> service = new eDVBService;
1002
1003                         ref.set(chid);
1004                         ref.setServiceID(service_id);
1005
1006                         for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1007                                         desc != (*s)->getDescriptors()->end(); ++desc)
1008                         {
1009                                 switch ((*desc)->getTag())
1010                                 {
1011                                 case SERVICE_DESCRIPTOR:
1012                                 {
1013                                         ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1014                                         ref.setServiceType(d.getServiceType());
1015                                         service->m_service_name = convertDVBUTF8(d.getServiceName());
1016                                         service->genSortName();
1017
1018                                         service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1019                                         SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1020                                         break;
1021                                 }
1022                                 case CA_IDENTIFIER_DESCRIPTOR:
1023                                 {
1024                                         CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1025                                         const CaSystemIdList &caids = *d.getCaSystemIds();
1026                                         SCAN_eDebugNoNewLine("CA ");
1027                                         for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1028                                         {
1029                                                 SCAN_eDebugNoNewLine("%04x ", *i);
1030                                                 service->m_ca.push_front(*i);
1031                                         }
1032                                         SCAN_eDebug("");
1033                                         break;
1034                                 }
1035                                 default:
1036                                         SCAN_eDebug("descr<%x>", (*desc)->getTag());
1037                                         break;
1038                                 }
1039                         }
1040
1041                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1042
1043                         if (i.second)
1044                         {
1045                                 m_last_service = i.first;
1046                                 m_event(evtNewService);
1047                         }
1048                 }
1049                 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1050                         m_abort_current_pmt = true;
1051                 else
1052                         m_pmts_to_read.erase(service_id);
1053         }
1054
1055         return 0;
1056 }
1057
1058 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1059 {
1060         connection = new eConnection(this, m_event.connect(event));
1061         return 0;
1062 }
1063
1064 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1065 {
1066         transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1067         transponders_total = m_ch_toScan.size() + transponders_done;
1068         services = m_new_services.size();
1069 }
1070
1071 void eDVBScan::getLastServiceName(std::string &last_service_name)
1072 {
1073         if (m_last_service == m_new_services.end())
1074                 last_service_name = "";
1075         else
1076                 last_service_name = m_last_service->second->m_service_name;
1077 }
1078
1079 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1080 {
1081         if (m_channel)
1082                 return m_channel->getFrontend(fe);
1083         fe = 0;
1084         return -1;
1085 }
1086
1087 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)
1088 {
1089         if (m_ch_current)
1090         {
1091                 tp = m_ch_current;
1092                 return 0;
1093         }
1094         tp = 0;
1095         return -1;
1096 }