refuse to stop scan after first invalid NIT in quick mode
[vuplus_dvbapp] / lib / dvb / scan.cpp
1 #include <lib/dvb/idvb.h>
2 #include <dvbsi++/descriptor_tag.h>
3 #include <dvbsi++/service_descriptor.h>
4 #include <dvbsi++/satellite_delivery_system_descriptor.h>
5 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
6 #include <dvbsi++/cable_delivery_system_descriptor.h>
7 #include <dvbsi++/ca_identifier_descriptor.h>
8 #include <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_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_BAT = 0; m_NIT = 0;
88
89         m_ready = 0;
90
91                 /* check what we need */
92         m_ready_all = readySDT;
93         
94         if (m_flags & scanNetworkSearch)
95                 m_ready_all |= readyNIT;
96         
97         if (m_flags & scanSearchBAT)
98                 m_ready_all |= readyBAT;
99
100         if (m_usePAT)
101                 m_ready_all |= readyPAT;
102
103         if (m_ch_toScan.empty())
104         {
105                 SCAN_eDebug("no channels left to scan.");
106                 SCAN_eDebug("%d channels scanned, %d were unavailable.", 
107                                 m_ch_scanned.size(), m_ch_unavailable.size());
108                 SCAN_eDebug("%d channels in database.", m_new_channels.size());
109                 m_event(evtFinish);
110                 return -ENOENT;
111         }
112         
113         m_ch_current = m_ch_toScan.front();
114         
115         m_ch_toScan.pop_front();
116         
117         if (m_channel->getFrontend(fe))
118         {
119                 m_event(evtFail);
120                 return -ENOTSUP;
121         }
122
123         int fetype;
124         fe->getFrontendType(fetype);
125         if ( fetype == iDVBFrontend::feSatellite)
126         {
127                 eDVBFrontendParametersSatellite p;
128                 m_ch_current->getDVBS(p);
129                 m_chid_current = eDVBChannelID(p.orbital_position << 16, -1, -1);
130         }
131         else
132                 m_chid_current = eDVBChannelID();
133
134         m_channel_state = iDVBChannel::state_idle;
135         if (fe->tune(*m_ch_current))
136         {
137                 return nextChannel();
138                 m_event(evtFail);
139                 return -EINVAL;
140         }
141                 
142         m_event(evtUpdate);
143         return 0;
144 }
145
146 RESULT eDVBScan::startFilter()
147 {
148         bool startSDT=true;
149         assert(m_demux);
150
151                         /* only start required filters filter */
152
153         if (m_ready_all & readyPAT)
154                 startSDT = m_ready & readyPAT;
155
156         m_SDT = 0;
157         if (startSDT && (m_ready_all & readySDT))
158         {
159                 m_SDT = new eTable<ServiceDescriptionSection>();
160                 if (m_ready & readyPAT && m_ready & validPAT)
161                 {
162                         std::vector<ProgramAssociationSection*>::const_iterator i =
163                                 m_PAT->getSections().begin();
164                         assert(i != m_PAT->getSections().end());
165                         int tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
166                         if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
167                                 return -1;
168                 }
169                 else if (m_SDT->start(m_demux, eDVBSDTSpec()))
170                         return -1;
171                 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
172         }
173
174         if (!(m_ready & readyPAT))
175         {
176                 m_PAT = 0;
177                 if (m_ready_all & readyPAT)
178                 {
179                         m_PAT = new eTable<ProgramAssociationSection>();
180                         if (m_PAT->start(m_demux, eDVBPATSpec()))
181                                 return -1;
182                         CONNECT(m_PAT->tableReady, eDVBScan::PATready);
183                 }
184
185                 m_NIT = 0;
186                 if (m_ready_all & readyNIT)
187                 {
188                         m_NIT = new eTable<NetworkInformationSection>();
189                         if (m_NIT->start(m_demux, eDVBNITSpec()))
190                                 return -1;
191                         CONNECT(m_NIT->tableReady, eDVBScan::NITready);
192                 }
193
194                 m_BAT = 0;
195                 if (m_ready_all & readyBAT)
196                 {
197                         m_BAT = new eTable<BouquetAssociationSection>();
198                         if (m_BAT->start(m_demux, eDVBBATSpec()))
199                                 return -1;
200                         CONNECT(m_BAT->tableReady, eDVBScan::BATready);
201                 }
202         }
203
204         return 0;
205 }
206
207 void eDVBScan::SDTready(int err)
208 {
209         SCAN_eDebug("got sdt");
210         m_ready |= readySDT;
211         if (!err)
212                 m_ready |= validSDT;
213         channelDone();
214 }
215
216 void eDVBScan::NITready(int err)
217 {
218         SCAN_eDebug("got nit, err %d", err);
219         m_ready |= readyNIT;
220         if (!err)
221                 m_ready |= validNIT;
222         channelDone();
223 }
224
225 void eDVBScan::BATready(int err)
226 {
227         SCAN_eDebug("got bat");
228         m_ready |= readyBAT;
229         if (!err)
230                 m_ready |= validBAT;
231         channelDone();
232 }
233
234 void eDVBScan::PATready(int err)
235 {
236         SCAN_eDebug("got pat");
237         m_ready |= readyPAT;
238         if (!err)
239                 m_ready |= validPAT;
240         startFilter(); // for starting the SDT filter
241 }
242
243 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
244 {
245                 /* add it to the list of known channels. */
246         if (chid)
247                 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
248 }
249
250 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
251 {
252                 /* check if we don't already have that channel ... */
253
254         int type;
255         feparm->getSystem(type);
256
257         switch(type)
258         {
259         case iDVBFrontend::feSatellite:
260         {
261                 eDVBFrontendParametersSatellite parm;
262                 feparm->getDVBS(parm);
263                 eDebug("try to add %d %d %d %d %d %d",
264                         parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
265                 break;
266         }
267         case iDVBFrontend::feCable:
268         {
269                 eDVBFrontendParametersCable parm;
270                 feparm->getDVBC(parm);
271                 eDebug("try to add %d %d %d %d",
272                         parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
273                 break;
274         }
275         case iDVBFrontend::feTerrestrial:
276         {
277                 eDVBFrontendParametersTerrestrial parm;
278                 feparm->getDVBT(parm);
279                 eDebug("try to add %d %d %d %d %d %d %d %d",
280                         parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
281                         parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
282                 break;
283         }
284         }
285
286         int found_count=0;
287                 /* ... in the list of channels to scan */
288         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
289         {
290                 if (sameChannel(*i, feparm))
291                 {
292                         if (!found_count)
293                         {
294                                 *i = feparm;  // update
295                                 eDebug("update");
296                         }
297                         else
298                         {
299                                 eDebug("remove dupe");
300                                 m_ch_toScan.erase(i++);
301                                 continue;
302                         }
303                         ++found_count;
304                 }
305                 ++i;
306         }
307
308         if (found_count > 0)
309         {
310                 eDebug("already in todo list");
311                 return;
312         }
313
314                 /* ... in the list of successfully scanned channels */
315         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
316                 if (sameChannel(*i, feparm))
317                 {
318                         eDebug("successfully scanned");
319                         return;
320                 }
321
322                 /* ... in the list of unavailable channels */
323         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
324                 if (sameChannel(*i, feparm, true))
325                 {
326                         eDebug("scanned but not available");
327                         return;
328                 }
329
330                 /* ... on the current channel */
331         if (sameChannel(m_ch_current, feparm))
332         {
333                 eDebug("is current");
334                 return;
335         }
336
337         eDebug("really add");
338                 /* otherwise, add it to the todo list. */
339         m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
340 }
341
342 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
343 {
344         int diff;
345         if (ch1->calculateDifference(ch2, diff, exact))
346                 return 0;
347         if (diff < 4000) // more than 4mhz difference?
348                 return 1;
349         return 0;
350 }
351
352 void eDVBScan::channelDone()
353 {
354         if (m_ready & validSDT)
355         {
356                 unsigned long hash = 0;
357
358                 // m_ch_current is not set, when eDVBScan is just used for a SDT update
359                 if (!m_ch_current)
360                         m_channel->getCurrentFrontendParameters(m_ch_current);
361
362                 m_ch_current->getHash(hash);
363                 
364                 eDVBNamespace dvbnamespace = buildNamespace(
365                         (**m_SDT->getSections().begin()).getOriginalNetworkId(),
366                         (**m_SDT->getSections().begin()).getTransportStreamId(),
367                         hash);
368                 
369                 SCAN_eDebug("SDT: ");
370                 std::vector<ServiceDescriptionSection*>::const_iterator i;
371                 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
372                         processSDT(dvbnamespace, **i);
373                 m_ready &= ~validSDT;
374         }
375         
376         if (m_ready & validNIT)
377         {
378                 int system;
379                 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
380                 m_ch_current->getSystem(system);
381                 SCAN_eDebug("dumping NIT");
382                 if (m_flags & clearToScanOnFirstNIT)
383                 {
384                         m_ch_toScan_backup = m_ch_toScan;
385                         m_ch_toScan.clear();
386                 }
387                 std::vector<NetworkInformationSection*>::const_iterator i;
388                 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
389                 {
390                         const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
391                         
392                         for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin()); 
393                                 tsinfo != tsinfovec.end(); ++tsinfo)
394                         {
395                                 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
396                                         (*tsinfo)->getOriginalNetworkId());
397                                 
398                                 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
399                                 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
400                                 
401                                 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
402                                                 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
403                                 {
404                                         switch ((*desc)->getTag())
405                                         {
406                                         case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
407                                         {
408                                                 if (system != iDVBFrontend::feCable)
409                                                         break; // when current locked transponder is no cable transponder ignore this descriptor
410                                                 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
411                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
412                                                 eDVBFrontendParametersCable cable;
413                                                 cable.set(d);
414                                                 feparm->setDVBC(cable);
415
416                                                 unsigned long hash=0;
417                                                 feparm->getHash(hash);
418                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
419
420                                                 addChannelToScan(
421                                                         eDVBChannelID(ns, tsid, onid),
422                                                         feparm);
423                                                 break;
424                                         }
425                                         case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
426                                         {
427                                                 if (system != iDVBFrontend::feTerrestrial)
428                                                         break; // when current locked transponder is no terrestrial transponder ignore this descriptor
429                                                 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
430                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
431                                                 eDVBFrontendParametersTerrestrial terr;
432                                                 terr.set(d);
433                                                 feparm->setDVBT(terr);
434
435                                                 unsigned long hash=0;
436                                                 feparm->getHash(hash);
437                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
438
439                                                 addChannelToScan(
440                                                         eDVBChannelID(ns, tsid, onid),
441                                                         feparm);
442                                                 break;
443                                         }
444                                         case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
445                                         {
446                                                 if (system != iDVBFrontend::feSatellite)
447                                                         break; // when current locked transponder is no satellite transponder ignore this descriptor
448
449                                                 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
450                                                 if (d.getFrequency() < 10000)
451                                                         break;
452                                                 
453                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
454                                                 eDVBFrontendParametersSatellite sat;
455                                                 sat.set(d);
456                                                 feparm->setDVBS(sat);
457                                                 unsigned long hash=0;
458                                                 feparm->getHash(hash);
459                                                 
460                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
461                                                 
462                                                 if ( m_chid_current.dvbnamespace.get() != -1 &&
463                                                         ((ns.get() ^ m_chid_current.dvbnamespace.get()) & 0xFFFF0000))
464                                                         SCAN_eDebug("dropping this transponder, it's on another satellite.");
465                                                 else
466                                                 {
467                                                         addChannelToScan(
468                                                                         eDVBChannelID(ns, tsid, onid),
469                                                                         feparm);
470                                                 }
471                                                 break;
472                                         }
473                                         default:
474                                                 SCAN_eDebug("descr<%x>", (*desc)->getTag());
475                                                 break;
476                                         }
477                                 }
478                         }
479                         
480                 }
481
482                         /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
483                            no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
484                            has been found.
485
486                            This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
487                         */
488                 if (m_flags & clearToScanOnFirstNIT)
489                 {
490                         if (m_ch_toScan.empty())
491                         {
492                                 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
493                                 m_ch_toScan = m_ch_toScan_backup;
494                         } else
495                                 m_flags &= ~clearToScanOnFirstNIT;
496                 }
497                 m_ready &= ~validNIT;
498         }
499         
500         if ((m_ready  & m_ready_all) != m_ready_all)
501                 return;
502         SCAN_eDebug("channel done!");
503         
504                 /* if we had services on this channel, we declare
505                    this channels as "known good". add it.
506                    
507                    (TODO: not yet implemented)
508                    a NIT entry could have possible overridden
509                    our frontend data with more exact data.
510                    
511                    (TODO: not yet implemented)
512                    the tuning process could have lead to more
513                    exact data than the user entered.
514                    
515                    The channel id was probably corrected
516                    by the data written in the SDT. this is
517                    important, as "initial transponder lists"
518                    usually don't have valid CHIDs (and that's
519                    good).
520                    
521                    These are the reasons for adding the transponder
522                    here, and not before.
523                 */
524
525         if (!m_chid_current)
526                 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
527         else
528         {
529                 addKnownGoodChannel(m_chid_current, m_ch_current);
530         
531                 m_ch_scanned.push_back(m_ch_current);
532
533                 for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
534                 {
535                         if (sameChannel(*i, m_ch_current))
536                         {
537                                 eDebug("remove dupe 2");
538                                 m_ch_toScan.erase(i++);
539                                 continue;
540                         }
541                         ++i;
542                 }
543         }
544
545         nextChannel();
546 }
547
548 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
549 {
550         m_flags = flags;
551         m_ch_toScan.clear();
552         m_ch_scanned.clear();
553         m_ch_unavailable.clear();
554         m_new_channels.clear();
555         m_new_services.clear();
556         m_last_service = m_new_services.end();
557
558         for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
559         {
560                 bool exist=false;
561                 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
562                 {
563                         if (sameChannel(*i, *ii, true))
564                         {
565                                 exist=true;
566                                 break;
567                         }
568                 }
569                 if (!exist)
570                         m_ch_toScan.push_back(*i);
571         }
572
573         nextChannel();
574 }
575
576 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
577 {
578         if (m_flags & scanRemoveServices)
579         {
580                 bool clearTerrestrial=false;
581                 bool clearCable=false;
582                 std::set<unsigned int> scanned_sat_positions;
583                 
584                 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
585                 for (;it != m_ch_scanned.end(); ++it)
586                 {
587                         int system;
588                         (*it)->getSystem(system);
589                         switch(system)
590                         {
591                                 case iDVBFrontend::feSatellite:
592                                 {
593                                         eDVBFrontendParametersSatellite sat_parm;
594                                         (*it)->getDVBS(sat_parm);
595                                         scanned_sat_positions.insert(sat_parm.orbital_position);
596                                         break;
597                                 }
598                                 case iDVBFrontend::feTerrestrial:
599                                 {
600                                         clearTerrestrial=true;
601                                         break;
602                                 }
603                                 case iDVBFrontend::feCable:
604                                 {
605                                         clearCable=true;
606                                         break;
607                                 }
608                         }
609                 }
610
611                 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
612                 {
613                         int system;
614                         (*it)->getSystem(system);
615                         switch(system)
616                         {
617                                 case iDVBFrontend::feSatellite:
618                                 {
619                                         eDVBFrontendParametersSatellite sat_parm;
620                                         (*it)->getDVBS(sat_parm);
621                                         scanned_sat_positions.insert(sat_parm.orbital_position);
622                                         break;
623                                 }
624                                 case iDVBFrontend::feTerrestrial:
625                                 {
626                                         clearTerrestrial=true;
627                                         break;
628                                 }
629                                 case iDVBFrontend::feCable:
630                                 {
631                                         clearCable=true;
632                                         break;
633                                 }
634                         }
635                 }
636
637                 if (clearTerrestrial)
638                 {
639                         eDVBChannelID chid;
640                         chid.dvbnamespace=0xEEEE0000;
641                         db->removeServices(chid);
642                 }
643                 if (clearCable)
644                 {
645                         eDVBChannelID chid;
646                         chid.dvbnamespace=0xFFFF0000;
647                         db->removeServices(chid);
648                 }
649                 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
650                 {
651                         eDVBChannelID chid;
652                         if (m_flags & scanDontRemoveFeeds)
653                                 chid.dvbnamespace = eDVBNamespace((*x)<<16);
654 //                      eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
655                         db->removeServices(chid, *x);
656                 }
657         }
658
659         for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator 
660                         ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
661                 db->addChannelToList(ch->first, ch->second);
662         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
663                 service(m_new_services.begin()); service != m_new_services.end(); ++service)
664         {
665                 ePtr<eDVBService> dvb_service;
666                 if (!db->getService(service->first, dvb_service))
667                 {
668                         if (dvb_service->m_flags & eDVBService::dxNoSDT)
669                                 continue;
670                         if (!(dvb_service->m_flags & eDVBService::dxHoldName))
671                         {
672                                 dvb_service->m_service_name = service->second->m_service_name;
673                                 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
674                         }
675                         dvb_service->m_provider_name = service->second->m_provider_name;
676                         if (service->second->m_ca.size())
677                                 dvb_service->m_ca = service->second->m_ca;
678                         if (!dontRemoveOldFlags) // do not remove new found flags when not wished
679                                 dvb_service->m_flags &= ~eDVBService::dxNewFound;
680                 }
681                 else
682                 {
683                         db->addService(service->first, service->second);
684                         service->second->m_flags |= eDVBService::dxNewFound;
685                 }
686         }
687 }
688
689 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
690 {
691         const ServiceDescriptionList &services = *sdt.getDescriptions();
692         SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
693         eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
694         
695         /* save correct CHID for this channel */
696         m_chid_current = chid;
697
698         for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
699         {
700                 SCAN_eDebugNoNewLine("SID %04x: ", (*s)->getServiceId());
701
702                 eServiceReferenceDVB ref;
703                 ePtr<eDVBService> service = new eDVBService;
704                 
705                 ref.set(chid);
706                 ref.setServiceID((*s)->getServiceId());
707
708                 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
709                                 desc != (*s)->getDescriptors()->end(); ++desc)
710                         if ((*desc)->getTag() == SERVICE_DESCRIPTOR)
711                                 ref.setServiceType(((ServiceDescriptor&)**desc).getServiceType());
712                 
713                 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
714                                 desc != (*s)->getDescriptors()->end(); ++desc)
715                 {
716                         switch ((*desc)->getTag())
717                         {
718                         case SERVICE_DESCRIPTOR:
719                         {
720                                 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
721                                 service->m_service_name = convertDVBUTF8(d.getServiceName());
722                                 service->genSortName();
723
724                                 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
725                                 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
726                                 break;
727                         }
728                         case CA_IDENTIFIER_DESCRIPTOR:
729                         {
730                                 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
731                                 const CaSystemIdList &caids = *d.getCaSystemIds();
732                                 SCAN_eDebugNoNewLine("CA ");
733                                 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
734                                 {
735                                         SCAN_eDebugNoNewLine("%04x ", *i);
736                                         service->m_ca.push_front(*i);
737                                 }
738                                 SCAN_eDebug("");
739                                 break;
740                         }
741                         default:
742                                 SCAN_eDebug("descr<%x>", (*desc)->getTag());
743                                 break;
744                         }
745                 }
746                 
747                 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
748                 
749                 if (i.second)
750                 {
751                         m_last_service = i.first;
752                         m_event(evtNewService);
753                 }
754         }
755         return 0;
756 }
757
758 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
759 {
760         connection = new eConnection(this, m_event.connect(event));
761         return 0;
762 }
763
764 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
765 {
766         transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
767         transponders_total = m_ch_toScan.size() + transponders_done;
768         services = m_new_services.size();
769 }
770
771 void eDVBScan::getLastServiceName(std::string &last_service_name)
772 {
773         if (m_last_service == m_new_services.end())
774                 last_service_name = "";
775         else
776                 last_service_name = m_last_service->second->m_service_name;
777 }