fix another subtitles bug
[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_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                 /* ... in the list of channels to scan */
287         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end(); ++i)
288                 if (sameChannel(*i, feparm))
289                 {
290                         *i = feparm;  // update
291                         eDebug("update");
292                         return;
293                 }
294
295                 /* ... in the list of successfully scanned channels */
296         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
297                 if (sameChannel(*i, feparm))
298                 {
299                         eDebug("successfully scanned");
300                         return;
301                 }
302
303                 /* ... in the list of unavailable channels */
304         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
305                 if (sameChannel(*i, feparm, true))
306                 {
307                         eDebug("scanned but not available");
308                         return;
309                 }
310
311                 /* ... on the current channel */
312         if (sameChannel(m_ch_current, feparm))
313         {
314                 eDebug("is current");
315                 return;
316         }
317
318         eDebug("really add");
319                 /* otherwise, add it to the todo list. */
320         m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
321 }
322
323 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
324 {
325         int diff;
326         if (ch1->calculateDifference(ch2, diff, exact))
327                 return 0;
328         if (diff < 4000) // more than 4mhz difference?
329                 return 1;
330         return 0;
331 }
332
333 void eDVBScan::channelDone()
334 {
335         if (m_ready & validSDT)
336         {
337                 unsigned long hash = 0;
338
339                 // m_ch_current is not set, when eDVBScan is just used for a SDT update
340                 if (!m_ch_current)
341                         m_channel->getCurrentFrontendParameters(m_ch_current);
342
343                 m_ch_current->getHash(hash);
344                 
345                 eDVBNamespace dvbnamespace = buildNamespace(
346                         (**m_SDT->getSections().begin()).getOriginalNetworkId(),
347                         (**m_SDT->getSections().begin()).getTransportStreamId(),
348                         hash);
349                 
350                 SCAN_eDebug("SDT: ");
351                 std::vector<ServiceDescriptionSection*>::const_iterator i;
352                 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
353                         processSDT(dvbnamespace, **i);
354                 m_ready &= ~validSDT;
355         }
356         
357         if (m_ready & validNIT)
358         {
359                 int system;
360                 m_ch_current->getSystem(system);
361                 SCAN_eDebug("dumping NIT");
362                 if (m_flags & clearToScanOnFirstNIT)
363                 {
364                         m_ch_toScan.clear();
365                         m_flags &= ~clearToScanOnFirstNIT;
366                 }
367                 std::vector<NetworkInformationSection*>::const_iterator i;
368                 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
369                 {
370                         const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
371                         
372                         for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin()); 
373                                 tsinfo != tsinfovec.end(); ++tsinfo)
374                         {
375                                 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
376                                         (*tsinfo)->getOriginalNetworkId());
377                                 
378                                 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
379                                 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
380                                 
381                                 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
382                                                 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
383                                 {
384                                         switch ((*desc)->getTag())
385                                         {
386                                         case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
387                                         {
388                                                 if (system != iDVBFrontend::feCable)
389                                                         break; // when current locked transponder is no cable transponder ignore this descriptor
390                                                 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
391                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
392                                                 eDVBFrontendParametersCable cable;
393                                                 cable.set(d);
394                                                 feparm->setDVBC(cable);
395
396                                                 unsigned long hash=0;
397                                                 feparm->getHash(hash);
398                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
399
400                                                 addChannelToScan(
401                                                         eDVBChannelID(ns, tsid, onid),
402                                                         feparm);
403                                                 break;
404                                         }
405                                         case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
406                                         {
407                                                 if (system != iDVBFrontend::feTerrestrial)
408                                                         break; // when current locked transponder is no terrestrial transponder ignore this descriptor
409                                                 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
410                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
411                                                 eDVBFrontendParametersTerrestrial terr;
412                                                 terr.set(d);
413                                                 feparm->setDVBT(terr);
414
415                                                 unsigned long hash=0;
416                                                 feparm->getHash(hash);
417                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
418
419                                                 addChannelToScan(
420                                                         eDVBChannelID(ns, tsid, onid),
421                                                         feparm);
422                                                 break;
423                                         }
424                                         case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
425                                         {
426                                                 if (system != iDVBFrontend::feSatellite)
427                                                         break; // when current locked transponder is no satellite transponder ignore this descriptor
428
429                                                 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
430                                                 if (d.getFrequency() < 10000)
431                                                         break;
432                                                 
433                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
434                                                 eDVBFrontendParametersSatellite sat;
435                                                 sat.set(d);
436                                                 feparm->setDVBS(sat);
437                                                 unsigned long hash=0;
438                                                 feparm->getHash(hash);
439                                                 
440                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
441                                                 
442                                                 if ( m_chid_current.dvbnamespace.get() != -1 &&
443                                                         ((ns.get() ^ m_chid_current.dvbnamespace.get()) & 0xFFFF0000))
444                                                         SCAN_eDebug("dropping this transponder, it's on another satellite.");
445                                                 else
446                                                 {
447                                                         addChannelToScan(
448                                                                         eDVBChannelID(ns, tsid, onid),
449                                                                         feparm);
450                                                 }
451                                                 break;
452                                         }
453                                         default:
454                                                 SCAN_eDebug("descr<%x>", (*desc)->getTag());
455                                                 break;
456                                         }
457                                 }
458                                 
459                         }
460                 }
461                 m_ready &= ~validNIT;
462         }
463         
464         if ((m_ready  & m_ready_all) != m_ready_all)
465                 return;
466         SCAN_eDebug("channel done!");
467         
468                 /* if we had services on this channel, we declare
469                    this channels as "known good". add it.
470                    
471                    (TODO: not yet implemented)
472                    a NIT entry could have possible overridden
473                    our frontend data with more exact data.
474                    
475                    (TODO: not yet implemented)
476                    the tuning process could have lead to more
477                    exact data than the user entered.
478                    
479                    The channel id was probably corrected
480                    by the data written in the SDT. this is
481                    important, as "initial transponder lists"
482                    usually don't have valid CHIDs (and that's
483                    good).
484                    
485                    These are the reasons for adding the transponder
486                    here, and not before.
487                 */
488
489         if (!m_chid_current)
490                 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
491         else
492                 addKnownGoodChannel(m_chid_current, m_ch_current);
493         
494         m_ch_scanned.push_back(m_ch_current);
495         nextChannel();
496 }
497
498 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
499 {
500         m_flags = flags;
501         m_ch_toScan.clear();
502         m_ch_scanned.clear();
503         m_ch_unavailable.clear();
504         m_new_channels.clear();
505         m_new_services.clear();
506         m_last_service = m_new_services.end();
507
508         for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
509         {
510                 bool exist=false;
511                 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
512                 {
513                         if (sameChannel(*i, *ii))
514                         {
515                                 exist=true;
516                                 break;
517                         }
518                 }
519                 if (!exist)
520                         m_ch_toScan.push_back(*i);
521         }
522
523         nextChannel();
524 }
525
526 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
527 {
528         if (m_flags & scanRemoveServices)
529         {
530                 bool clearTerrestrial=false;
531                 bool clearCable=false;
532                 std::set<unsigned int> scanned_sat_positions;
533                 
534                 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
535                 for (;it != m_ch_scanned.end(); ++it)
536                 {
537                         int system;
538                         (*it)->getSystem(system);
539                         switch(system)
540                         {
541                                 case iDVBFrontend::feSatellite:
542                                 {
543                                         eDVBFrontendParametersSatellite sat_parm;
544                                         (*it)->getDVBS(sat_parm);
545                                         scanned_sat_positions.insert(sat_parm.orbital_position);
546                                         break;
547                                 }
548                                 case iDVBFrontend::feTerrestrial:
549                                 {
550                                         clearTerrestrial=true;
551                                         break;
552                                 }
553                                 case iDVBFrontend::feCable:
554                                 {
555                                         clearCable=true;
556                                         break;
557                                 }
558                         }
559                 }
560
561                 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
562                 {
563                         int system;
564                         (*it)->getSystem(system);
565                         switch(system)
566                         {
567                                 case iDVBFrontend::feSatellite:
568                                 {
569                                         eDVBFrontendParametersSatellite sat_parm;
570                                         (*it)->getDVBS(sat_parm);
571                                         scanned_sat_positions.insert(sat_parm.orbital_position);
572                                         break;
573                                 }
574                                 case iDVBFrontend::feTerrestrial:
575                                 {
576                                         clearTerrestrial=true;
577                                         break;
578                                 }
579                                 case iDVBFrontend::feCable:
580                                 {
581                                         clearCable=true;
582                                         break;
583                                 }
584                         }
585                 }
586
587                 if (clearTerrestrial)
588                 {
589                         eDVBChannelID chid;
590                         chid.dvbnamespace=0xEEEE0000;
591                         db->removeServices(chid);
592                 }
593                 if (clearCable)
594                 {
595                         eDVBChannelID chid;
596                         chid.dvbnamespace=0xFFFF0000;
597                         db->removeServices(chid);
598                 }
599                 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
600                 {
601                         eDVBChannelID chid;
602                         if (m_flags & scanDontRemoveFeeds)
603                                 chid.dvbnamespace = eDVBNamespace((*x)<<16);
604 //                      eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
605                         db->removeServices(chid, *x);
606                 }
607         }
608
609         for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator 
610                         ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
611                 db->addChannelToList(ch->first, ch->second);
612         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
613                 service(m_new_services.begin()); service != m_new_services.end(); ++service)
614         {
615                 ePtr<eDVBService> dvb_service;
616                 if (!db->getService(service->first, dvb_service))
617                 {
618                         if (dvb_service->m_flags & eDVBService::dxNoSDT)
619                                 continue;
620                         if (!(dvb_service->m_flags & eDVBService::dxHoldName))
621                         {
622                                 dvb_service->m_service_name = service->second->m_service_name;
623                                 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
624                         }
625                         dvb_service->m_provider_name = service->second->m_provider_name;
626                         if (service->second->m_ca.size())
627                                 dvb_service->m_ca = service->second->m_ca;
628                         if (!dontRemoveOldFlags) // do not remove new found flags when not wished
629                                 dvb_service->m_flags &= ~eDVBService::dxNewFound;
630                 }
631                 else
632                 {
633                         db->addService(service->first, service->second);
634                         service->second->m_flags |= eDVBService::dxNewFound;
635                 }
636         }
637 }
638
639 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
640 {
641         const ServiceDescriptionList &services = *sdt.getDescriptions();
642         SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
643         eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
644         
645         /* save correct CHID for this channel */
646         m_chid_current = chid;
647
648         for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
649         {
650                 SCAN_eDebugNoNewLine("SID %04x: ", (*s)->getServiceId());
651
652                 eServiceReferenceDVB ref;
653                 ePtr<eDVBService> service = new eDVBService;
654                 
655                 ref.set(chid);
656                 ref.setServiceID((*s)->getServiceId());
657
658                 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
659                                 desc != (*s)->getDescriptors()->end(); ++desc)
660                         if ((*desc)->getTag() == SERVICE_DESCRIPTOR)
661                                 ref.setServiceType(((ServiceDescriptor&)**desc).getServiceType());
662                 
663                 for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
664                                 desc != (*s)->getDescriptors()->end(); ++desc)
665                 {
666                         switch ((*desc)->getTag())
667                         {
668                         case SERVICE_DESCRIPTOR:
669                         {
670                                 ServiceDescriptor &d = (ServiceDescriptor&)**desc;
671                                 service->m_service_name = convertDVBUTF8(d.getServiceName());
672                                 service->genSortName();
673
674                                 service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
675                                 SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
676                                 break;
677                         }
678                         case CA_IDENTIFIER_DESCRIPTOR:
679                         {
680                                 CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
681                                 const CaSystemIdList &caids = *d.getCaSystemIds();
682                                 SCAN_eDebugNoNewLine("CA ");
683                                 for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
684                                 {
685                                         SCAN_eDebugNoNewLine("%04x ", *i);
686                                         service->m_ca.push_front(*i);
687                                 }
688                                 SCAN_eDebug("");
689                                 break;
690                         }
691                         default:
692                                 SCAN_eDebug("descr<%x>", (*desc)->getTag());
693                                 break;
694                         }
695                 }
696                 
697                 std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
698                 
699                 if (i.second)
700                 {
701                         m_last_service = i.first;
702                         m_event(evtNewService);
703                 }
704         }
705         return 0;
706 }
707
708 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
709 {
710         connection = new eConnection(this, m_event.connect(event));
711         return 0;
712 }
713
714 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
715 {
716         transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
717         transponders_total = m_ch_toScan.size() + transponders_done;
718         services = m_new_services.size();
719 }
720
721 void eDVBScan::getLastServiceName(std::string &last_service_name)
722 {
723         if (m_last_service == m_new_services.end())
724                 last_service_name = "";
725         else
726                 last_service_name = m_last_service->second->m_service_name;
727 }