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