fix write
[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                                 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                                                 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                 SCAN_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                 SCAN_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                 SCAN_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                                 SCAN_eDebug("update");
431                         }
432                         else
433                         {
434                                 SCAN_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                 SCAN_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                         SCAN_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                         SCAN_eDebug("scanned but not available");
462                         return;
463                 }
464
465                 /* ... on the current channel */
466         if (sameChannel(m_ch_current, feparm))
467         {
468                 SCAN_eDebug("is current");
469                 return;
470         }
471
472         SCAN_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                 int system;
520                 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
521                 m_ch_current->getSystem(system);
522                 SCAN_eDebug("dumping NIT");
523                 if (m_flags & clearToScanOnFirstNIT)
524                 {
525                         m_ch_toScan_backup = m_ch_toScan;
526                         m_ch_toScan.clear();
527                 }
528                 std::vector<NetworkInformationSection*>::const_iterator i;
529                 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
530                 {
531                         const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
532                         
533                         for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin()); 
534                                 tsinfo != tsinfovec.end(); ++tsinfo)
535                         {
536                                 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
537                                         (*tsinfo)->getOriginalNetworkId());
538                                 
539                                 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
540                                 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
541                                 
542                                 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
543                                                 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
544                                 {
545                                         switch ((*desc)->getTag())
546                                         {
547                                         case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
548                                         {
549                                                 if (system != iDVBFrontend::feCable)
550                                                         break; // when current locked transponder is no cable transponder ignore this descriptor
551                                                 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
552                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
553                                                 eDVBFrontendParametersCable cable;
554                                                 cable.set(d);
555                                                 feparm->setDVBC(cable);
556
557                                                 unsigned long hash=0;
558                                                 feparm->getHash(hash);
559                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
560
561                                                 addChannelToScan(
562                                                         eDVBChannelID(ns, tsid, onid),
563                                                         feparm);
564                                                 break;
565                                         }
566                                         case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
567                                         {
568                                                 if (system != iDVBFrontend::feTerrestrial)
569                                                         break; // when current locked transponder is no terrestrial transponder ignore this descriptor
570                                                 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
571                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
572                                                 eDVBFrontendParametersTerrestrial terr;
573                                                 terr.set(d);
574                                                 feparm->setDVBT(terr);
575
576                                                 unsigned long hash=0;
577                                                 feparm->getHash(hash);
578                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
579
580                                                 addChannelToScan(
581                                                         eDVBChannelID(ns, tsid, onid),
582                                                         feparm);
583                                                 break;
584                                         }
585                                         case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
586                                         {
587                                                 if (system != iDVBFrontend::feSatellite)
588                                                         break; // when current locked transponder is no satellite transponder ignore this descriptor
589
590                                                 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
591                                                 if (d.getFrequency() < 10000)
592                                                         break;
593                                                 
594                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
595                                                 eDVBFrontendParametersSatellite sat;
596                                                 sat.set(d);
597
598                                                 eDVBFrontendParametersSatellite p;
599                                                 m_ch_current->getDVBS(p);
600
601                                                 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
602                                                         sat.orbital_position = p.orbital_position;
603
604                                                 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
605                                                 {
606                                                         SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
607                                                         sat.orbital_position = p.orbital_position;
608                                                 }
609
610                                                 feparm->setDVBS(sat);
611
612                                                 if ( p.orbital_position != sat.orbital_position)
613                                                         SCAN_eDebug("dropping this transponder, it's on another satellite.");
614                                                 else
615                                                 {
616                                                         unsigned long hash=0;
617                                                         feparm->getHash(hash);
618                                                         addChannelToScan(
619                                                                         eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
620                                                                         feparm);
621                                                 }
622                                                 break;
623                                         }
624                                         default:
625                                                 SCAN_eDebug("descr<%x>", (*desc)->getTag());
626                                                 break;
627                                         }
628                                 }
629                         }
630                         
631                 }
632
633                         /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
634                            no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
635                            has been found.
636
637                            This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
638                         */
639                 if (m_flags & clearToScanOnFirstNIT)
640                 {
641                         if (m_ch_toScan.empty())
642                         {
643                                 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
644                                 m_ch_toScan = m_ch_toScan_backup;
645                         } else
646                                 m_flags &= ~clearToScanOnFirstNIT;
647                 }
648                 m_ready &= ~validNIT;
649         }
650
651         if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
652         {
653                 if (m_abort_current_pmt)
654                 {
655                         m_abort_current_pmt = false;
656                         PMTready(-1);
657                 }
658                 return;
659         }
660
661         SCAN_eDebug("channel done!");
662         
663                 /* if we had services on this channel, we declare
664                    this channels as "known good". add it.
665                    
666                    (TODO: not yet implemented)
667                    a NIT entry could have possible overridden
668                    our frontend data with more exact data.
669                    
670                    (TODO: not yet implemented)
671                    the tuning process could have lead to more
672                    exact data than the user entered.
673                    
674                    The channel id was probably corrected
675                    by the data written in the SDT. this is
676                    important, as "initial transponder lists"
677                    usually don't have valid CHIDs (and that's
678                    good).
679                    
680                    These are the reasons for adding the transponder
681                    here, and not before.
682                 */
683
684         for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
685         {
686                 int type;
687                 eServiceReferenceDVB ref;
688                 ePtr<eDVBService> service = new eDVBService;
689
690                 if (!m_chid_current)
691                 {
692                         unsigned long hash = 0;
693
694                         // m_ch_current is not set, when eDVBScan is just used for a SDT update
695                         if (!m_ch_current)
696                         {
697                                 unsigned int channelFlags;
698                                 m_channel->getCurrentFrontendParameters(m_ch_current);
699                                 m_ch_current->getFlags(channelFlags);
700                                 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
701                                         m_flags |= scanOnlyFree;
702                         }
703
704                         m_ch_current->getHash(hash);
705
706                         m_chid_current = eDVBChannelID(
707                                 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
708                                 m_pat_tsid, eOriginalNetworkID(0));
709                 }
710
711                 if (m_pmt_in_progress->second.serviceType == 1)
712                         SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
713                 else if (m_pmt_in_progress->second.serviceType == 2)
714                         SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
715                 else
716                         SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
717
718                 ref.set(m_chid_current);
719                 ref.setServiceID(m_pmt_in_progress->first);
720                 ref.setServiceType(m_pmt_in_progress->second.serviceType);
721
722                 if (!m_ch_current->getSystem(type))
723                 {
724                         char sname[255];
725                         char pname[255];
726                         memset(pname, 0, sizeof(pname));
727                         memset(sname, 0, sizeof(sname));
728                         switch(type)
729                         {
730                                 case iDVBFrontend::feSatellite:
731                                 {
732                                         eDVBFrontendParametersSatellite parm;
733                                         m_ch_current->getDVBS(parm);
734                                         snprintf(sname, 255, "%d%c SID 0x%02x",
735                                                         parm.frequency/1000,
736                                                         parm.polarisation ? 'V' : 'H',
737                                                         m_pmt_in_progress->first);
738                                         snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
739                                                 parm.system ? "DVB-S2" : "DVB-S",
740                                                 parm.modulation == 1 ? "QPSK" : "8PSK",
741                                                 parm.frequency/1000,
742                                                 parm.polarisation ? 'V' : 'H',
743                                                 parm.orbital_position/10,
744                                                 parm.orbital_position%10,
745                                                 parm.orbital_position > 0 ? 'E' : 'W');
746                                         break;
747                                 }
748                                 case iDVBFrontend::feTerrestrial:
749                                 {
750                                         eDVBFrontendParametersTerrestrial parm;
751                                         m_ch_current->getDVBT(parm);
752                                         snprintf(sname, 255, "%d SID 0x%02x",
753                                                 parm.frequency/1000,
754                                                 m_pmt_in_progress->first);
755                                         break;
756                                 }
757                                 case iDVBFrontend::feCable:
758                                 {
759                                         eDVBFrontendParametersCable parm;
760                                         m_ch_current->getDVBC(parm);
761                                         snprintf(sname, 255, "%d SID 0x%02x",
762                                                 parm.frequency/1000,
763                                                 m_pmt_in_progress->first);
764                                         break;
765                                 }
766                         }
767                         SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
768                         service->m_service_name = convertDVBUTF8(sname);
769                         service->genSortName();
770                         service->m_provider_name = pname;
771                 }
772
773                 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
774
775                 if (i.second)
776                 {
777                         m_last_service = i.first;
778                         m_event(evtNewService);
779                 }
780                 m_pmts_to_read.erase(m_pmt_in_progress++);
781         }
782
783         if (!m_chid_current)
784                 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
785         else
786                 addKnownGoodChannel(m_chid_current, m_ch_current);
787         
788         m_ch_scanned.push_back(m_ch_current);
789         
790         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
791         {
792                 if (sameChannel(*i, m_ch_current))
793                 {
794                         SCAN_eDebug("remove dupe 2");
795                         m_ch_toScan.erase(i++);
796                         continue;
797                 }
798                 ++i;
799         }
800         
801         nextChannel();
802 }
803
804 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
805 {
806         m_flags = flags;
807         m_ch_toScan.clear();
808         m_ch_scanned.clear();
809         m_ch_unavailable.clear();
810         m_new_channels.clear();
811         m_new_services.clear();
812         m_last_service = m_new_services.end();
813
814         for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
815         {
816                 bool exist=false;
817                 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
818                 {
819                         if (sameChannel(*i, *ii, true))
820                         {
821                                 exist=true;
822                                 break;
823                         }
824                 }
825                 if (!exist)
826                         m_ch_toScan.push_back(*i);
827         }
828
829         nextChannel();
830 }
831
832 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
833 {
834         if (m_flags & scanRemoveServices)
835         {
836                 bool clearTerrestrial=false;
837                 bool clearCable=false;
838                 std::set<unsigned int> scanned_sat_positions;
839                 
840                 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
841                 for (;it != m_ch_scanned.end(); ++it)
842                 {
843                         if (m_flags & scanDontRemoveUnscanned)
844                                 db->removeServices(&(*(*it)));
845                         else
846                         {
847                                 int system;
848                                 (*it)->getSystem(system);
849                                 switch(system)
850                                 {
851                                         case iDVBFrontend::feSatellite:
852                                         {
853                                                 eDVBFrontendParametersSatellite sat_parm;
854                                                 (*it)->getDVBS(sat_parm);
855                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
856                                                 break;
857                                         }
858                                         case iDVBFrontend::feTerrestrial:
859                                         {
860                                                 clearTerrestrial=true;
861                                                 break;
862                                         }
863                                         case iDVBFrontend::feCable:
864                                         {
865                                                 clearCable=true;
866                                                 break;
867                                         }
868                                 }
869                         }
870                 }
871
872                 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
873                 {
874                         if (m_flags & scanDontRemoveUnscanned)
875                                 db->removeServices(&(*(*it)));
876                         else
877                         {
878                                 int system;
879                                 (*it)->getSystem(system);
880                                 switch(system)
881                                 {
882                                         case iDVBFrontend::feSatellite:
883                                         {
884                                                 eDVBFrontendParametersSatellite sat_parm;
885                                                 (*it)->getDVBS(sat_parm);
886                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
887                                                 break;
888                                         }
889                                         case iDVBFrontend::feTerrestrial:
890                                         {
891                                                 clearTerrestrial=true;
892                                                 break;
893                                         }
894                                         case iDVBFrontend::feCable:
895                                         {
896                                                 clearCable=true;
897                                                 break;
898                                         }
899                                 }
900                         }
901                 }
902
903                 if (clearTerrestrial)
904                 {
905                         eDVBChannelID chid;
906                         chid.dvbnamespace=0xEEEE0000;
907                         db->removeServices(chid);
908                 }
909                 if (clearCable)
910                 {
911                         eDVBChannelID chid;
912                         chid.dvbnamespace=0xFFFF0000;
913                         db->removeServices(chid);
914                 }
915                 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
916                 {
917                         eDVBChannelID chid;
918                         if (m_flags & scanDontRemoveFeeds)
919                                 chid.dvbnamespace = eDVBNamespace((*x)<<16);
920 //                      eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
921                         db->removeServices(chid, *x);
922                 }
923         }
924
925         for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator 
926                         ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
927         {
928                 if (m_flags & scanOnlyFree)
929                 {
930                         eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
931                         ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
932                 }
933                 db->addChannelToList(ch->first, ch->second);
934         }
935
936         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
937                 service(m_new_services.begin()); service != m_new_services.end(); ++service)
938         {
939                 ePtr<eDVBService> dvb_service;
940                 if (!db->getService(service->first, dvb_service))
941                 {
942                         if (dvb_service->m_flags & eDVBService::dxNoSDT)
943                                 continue;
944                         if (!(dvb_service->m_flags & eDVBService::dxHoldName))
945                         {
946                                 dvb_service->m_service_name = service->second->m_service_name;
947                                 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
948                         }
949                         dvb_service->m_provider_name = service->second->m_provider_name;
950                         if (service->second->m_ca.size())
951                                 dvb_service->m_ca = service->second->m_ca;
952                         if (!dontRemoveOldFlags) // do not remove new found flags when not wished
953                                 dvb_service->m_flags &= ~eDVBService::dxNewFound;
954                 }
955                 else
956                 {
957                         db->addService(service->first, service->second);
958                         if (!(m_flags & scanRemoveServices))
959                                 service->second->m_flags |= eDVBService::dxNewFound;
960                 }
961         }
962 }
963
964 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
965 {
966         const ServiceDescriptionList &services = *sdt.getDescriptions();
967         SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
968         eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
969         
970         /* save correct CHID for this channel */
971         m_chid_current = chid;
972
973         for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
974         {
975                 unsigned short service_id = (*s)->getServiceId();
976                 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
977                 bool add = true;
978
979                 if (m_flags & scanOnlyFree)
980                 {
981                         std::map<unsigned short, service>::iterator it =
982                                 m_pmts_to_read.find(service_id);
983                         if (it != m_pmts_to_read.end())
984                         {
985                                 if (it->second.scrambled)
986                                 {
987                                         SCAN_eDebug("is scrambled!");
988                                         add = false;
989                                 }
990                         }
991                         else
992                                 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
993                 }
994
995                 if (add)
996                 {
997                         eServiceReferenceDVB ref;
998                         ePtr<eDVBService> service = new eDVBService;
999
1000                         ref.set(chid);
1001                         ref.setServiceID(service_id);
1002
1003                         for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1004                                         desc != (*s)->getDescriptors()->end(); ++desc)
1005                         {
1006                                 switch ((*desc)->getTag())
1007                                 {
1008                                 case SERVICE_DESCRIPTOR:
1009                                 {
1010                                         ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1011                                         ref.setServiceType(d.getServiceType());
1012                                         service->m_service_name = convertDVBUTF8(d.getServiceName());
1013                                         service->genSortName();
1014
1015                                         service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1016                                         SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1017                                         break;
1018                                 }
1019                                 case CA_IDENTIFIER_DESCRIPTOR:
1020                                 {
1021                                         CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1022                                         const CaSystemIdList &caids = *d.getCaSystemIds();
1023                                         SCAN_eDebugNoNewLine("CA ");
1024                                         for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1025                                         {
1026                                                 SCAN_eDebugNoNewLine("%04x ", *i);
1027                                                 service->m_ca.push_front(*i);
1028                                         }
1029                                         SCAN_eDebug("");
1030                                         break;
1031                                 }
1032                                 default:
1033                                         SCAN_eDebug("descr<%x>", (*desc)->getTag());
1034                                         break;
1035                                 }
1036                         }
1037
1038                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1039
1040                         if (i.second)
1041                         {
1042                                 m_last_service = i.first;
1043                                 m_event(evtNewService);
1044                         }
1045                 }
1046                 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1047                         m_abort_current_pmt = true;
1048                 else
1049                         m_pmts_to_read.erase(service_id);
1050         }
1051
1052         return 0;
1053 }
1054
1055 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1056 {
1057         connection = new eConnection(this, m_event.connect(event));
1058         return 0;
1059 }
1060
1061 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1062 {
1063         transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1064         transponders_total = m_ch_toScan.size() + transponders_done;
1065         services = m_new_services.size();
1066 }
1067
1068 void eDVBScan::getLastServiceName(std::string &last_service_name)
1069 {
1070         if (m_last_service == m_new_services.end())
1071                 last_service_name = "";
1072         else
1073                 last_service_name = m_last_service->second->m_service_name;
1074 }
1075
1076 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1077 {
1078         if (m_channel)
1079                 return m_channel->getFrontend(fe);
1080         fe = 0;
1081         return -1;
1082 }
1083
1084 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)
1085 {
1086         if (m_ch_current)
1087         {
1088                 tp = m_ch_current;
1089                 return 0;
1090         }
1091         tp = 0;
1092         return -1;
1093 }