scan.cpp: sync audio/video detection with current pmt.cpp code
[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 #define SCAN_eDebug(x...) do { if (m_scan_debug) eDebug(x); } while(0)
17 #define SCAN_eDebugNoNewLine(x...) do { if (m_scan_debug) eDebugNoNewLine(x); } while(0)
18
19 DEFINE_REF(eDVBScan);
20
21 eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug)
22         :m_channel(channel), m_channel_state(iDVBChannel::state_idle)
23         ,m_ready(0), m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT)
24         ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0)
25         ,m_usePAT(usePAT), m_scan_debug(debug)
26 {
27         if (m_channel->getDemux(m_demux))
28                 SCAN_eDebug("scan: failed to allocate demux!");
29         m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
30 }
31
32 eDVBScan::~eDVBScan()
33 {
34 }
35
36 int eDVBScan::isValidONIDTSID(int orbital_position, eOriginalNetworkID onid, eTransportStreamID tsid)
37 {
38         switch (onid.get())
39         {
40         case 0:
41         case 0x1111:
42                 return 0;
43         case 0x13E:  // workaround for 11258H and 11470V on hotbird with same ONID/TSID (0x13E/0x578)
44                 return orbital_position != 130 || tsid != 0x578;
45         case 1:
46                 return orbital_position == 192;
47         case 0x00B1:
48                 return tsid != 0x00B0;
49         case 0x00eb:
50                 return tsid != 0x4321;
51         case 0x0002:
52                 return abs(orbital_position-282) < 6;
53         default:
54                 return onid.get() < 0xFF00;
55         }
56 }
57
58 eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash)
59 {
60                 // on valid ONIDs, ignore frequency ("sub network") part
61         if (isValidONIDTSID((hash >> 16) & 0xFFFF, onid, tsid))
62                 hash &= ~0xFFFF;
63         return eDVBNamespace(hash);
64 }
65
66 void eDVBScan::stateChange(iDVBChannel *ch)
67 {
68         int state;
69         if (ch->getState(state))
70                 return;
71         if (m_channel_state == state)
72                 return;
73         
74         if (state == iDVBChannel::state_ok)
75         {
76                 startFilter();
77                 m_channel_state = state;
78         } else if (state == iDVBChannel::state_failed)
79         {
80                 m_ch_unavailable.push_back(m_ch_current);
81                 nextChannel();
82         }
83                         /* unavailable will timeout, anyway. */
84 }
85
86 RESULT eDVBScan::nextChannel()
87 {
88         ePtr<iDVBFrontend> fe;
89
90         m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0;
91
92         m_ready = 0;
93
94         m_pat_tsid = eTransportStreamID();
95
96                 /* check what we need */
97         m_ready_all = readySDT;
98         
99         if (m_flags & scanNetworkSearch)
100                 m_ready_all |= readyNIT;
101         
102         if (m_flags & scanSearchBAT)
103                 m_ready_all |= readyBAT;
104
105         if (m_usePAT)
106                 m_ready_all |= readyPAT;
107
108         if (m_ch_toScan.empty())
109         {
110                 SCAN_eDebug("no channels left to scan.");
111                 SCAN_eDebug("%d channels scanned, %d were unavailable.", 
112                                 m_ch_scanned.size(), m_ch_unavailable.size());
113                 SCAN_eDebug("%d channels in database.", m_new_channels.size());
114                 m_event(evtFinish);
115                 return -ENOENT;
116         }
117         
118         m_ch_current = m_ch_toScan.front();
119         
120         m_ch_toScan.pop_front();
121         
122         if (m_channel->getFrontend(fe))
123         {
124                 m_event(evtFail);
125                 return -ENOTSUP;
126         }
127
128         m_chid_current = eDVBChannelID();
129
130         m_channel_state = iDVBChannel::state_idle;
131
132         if (fe->tune(*m_ch_current))
133                 return nextChannel();
134
135         m_event(evtUpdate);
136         return 0;
137 }
138
139 RESULT eDVBScan::startFilter()
140 {
141         bool startSDT=true;
142         ASSERT(m_demux);
143
144                         /* only start required filters filter */
145
146         if (m_ready_all & readyPAT)
147                 startSDT = m_ready & readyPAT;
148
149         // m_ch_current is not set, when eDVBScan is just used for a SDT update
150         if (!m_ch_current)
151         {
152                 unsigned int channelFlags;
153                 m_channel->getCurrentFrontendParameters(m_ch_current);
154                 m_ch_current->getFlags(channelFlags);
155                 if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
156                         m_flags |= scanOnlyFree;
157         }
158
159         m_SDT = 0;
160         if (startSDT && (m_ready_all & readySDT))
161         {
162                 m_SDT = new eTable<ServiceDescriptionSection>(m_scan_debug);
163                 int tsid=-1;
164                 if (m_ready & readyPAT && m_ready & validPAT)
165                 {
166                         std::vector<ProgramAssociationSection*>::const_iterator i =
167                                 m_PAT->getSections().begin();
168                         ASSERT(i != m_PAT->getSections().end());
169                         tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
170                         m_pat_tsid = eTransportStreamID(tsid);
171                         for (; i != m_PAT->getSections().end(); ++i)
172                         {
173                                 const ProgramAssociationSection &pat = **i;
174                                 ProgramAssociationConstIterator program = pat.getPrograms()->begin();
175                                 for (; program != pat.getPrograms()->end(); ++program)
176                                         m_pmts_to_read.insert(std::pair<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
177                         }
178                         m_PMT = new eTable<ProgramMapSection>(m_scan_debug);
179                         CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
180                         PMTready(-2);
181                         // KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
182
183                         {
184                                 int type;
185                                 m_ch_current->getSystem(type);
186                                 if (type == iDVBFrontend::feCable)
187                                 {
188                                         eDVBFrontendParametersCable parm;
189                                         m_ch_current->getDVBC(parm);
190                                         if ((tsid == 0x00d7 && abs(parm.frequency-618000) < 2000) ||
191                                                 (tsid == 0x00d8 && abs(parm.frequency-626000) < 2000))
192                                                 tsid = -1;
193                                 }
194                         }
195                 }
196                 if (tsid == -1)
197                 {
198                         if (m_SDT->start(m_demux, eDVBSDTSpec()))
199                                 return -1;
200                 }
201                 else if (m_SDT->start(m_demux, eDVBSDTSpec(tsid, true)))
202                         return -1;
203                 CONNECT(m_SDT->tableReady, eDVBScan::SDTready);
204         }
205
206         if (!(m_ready & readyPAT))
207         {
208                 m_PAT = 0;
209                 if (m_ready_all & readyPAT)
210                 {
211                         m_PAT = new eTable<ProgramAssociationSection>(m_scan_debug);
212                         if (m_PAT->start(m_demux, eDVBPATSpec(4000)))
213                                 return -1;
214                         CONNECT(m_PAT->tableReady, eDVBScan::PATready);
215                 }
216
217                 m_NIT = 0;
218                 if (m_ready_all & readyNIT)
219                 {
220                         m_NIT = new eTable<NetworkInformationSection>(m_scan_debug);
221                         if (m_NIT->start(m_demux, eDVBNITSpec()))
222                                 return -1;
223                         CONNECT(m_NIT->tableReady, eDVBScan::NITready);
224                 }
225
226                 m_BAT = 0;
227                 if (m_ready_all & readyBAT)
228                 {
229                         m_BAT = new eTable<BouquetAssociationSection>(m_scan_debug);
230                         if (m_BAT->start(m_demux, eDVBBATSpec()))
231                                 return -1;
232                         CONNECT(m_BAT->tableReady, eDVBScan::BATready);
233                 }
234         }
235         return 0;
236 }
237
238 void eDVBScan::SDTready(int err)
239 {
240         SCAN_eDebug("got sdt %d", err);
241         m_ready |= readySDT;
242         if (!err)
243                 m_ready |= validSDT;
244         channelDone();
245 }
246
247 void eDVBScan::NITready(int err)
248 {
249         SCAN_eDebug("got nit, err %d", err);
250         m_ready |= readyNIT;
251         if (!err)
252                 m_ready |= validNIT;
253         channelDone();
254 }
255
256 void eDVBScan::BATready(int err)
257 {
258         SCAN_eDebug("got bat");
259         m_ready |= readyBAT;
260         if (!err)
261                 m_ready |= validBAT;
262         channelDone();
263 }
264
265 void eDVBScan::PATready(int err)
266 {
267         SCAN_eDebug("got pat");
268         m_ready |= readyPAT;
269         if (!err)
270                 m_ready |= validPAT;
271         startFilter(); // for starting the SDT filter
272 }
273
274 void eDVBScan::PMTready(int err)
275 {
276         SCAN_eDebug("got pmt %d", err);
277         if (!err)
278         {
279                 bool scrambled = false;
280                 bool have_audio = false;
281                 bool have_video = false;
282                 unsigned short pcrpid = 0xFFFF;
283                 std::vector<ProgramMapSection*>::const_iterator i;
284
285                 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
286                 {
287                         const ProgramMapSection &pmt = **i;
288                         if (pcrpid == 0xFFFF)
289                                 pcrpid = pmt.getPcrPid();
290                         else
291                                 SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
292                         ElementaryStreamInfoConstIterator es;
293                         for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
294                         {
295                                 int isaudio = 0, isvideo = 0, is_scrambled = 0;
296                                 switch ((*es)->getType())
297                                 {
298                                 case 0xEA: // TS_PSI_ST_SMPTE_VC1
299                                 case 0x1b: // AVC Video Stream (MPEG4 H264)
300                                 case 0x10: // MPEG 4 Part 2
301                                 case 0x01: // MPEG 1 video
302                                 case 0x02: // MPEG 2 video
303                                         isvideo = 1;
304                                         //break; fall through !!!
305                                 case 0x03: // MPEG 1 audio
306                                 case 0x04: // MPEG 2 audio
307                                 case 0x0f: // MPEG 2 AAC
308                                 case 0x11: // MPEG 4 AAC
309                                         if (!isvideo)
310                                                 isaudio = 1;
311                                 case 0x06: // PES Private
312                                 case 0x81: // user private
313                                         for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
314                                                         desc != (*es)->getDescriptors()->end(); ++desc)
315                                         {
316                                                 uint8_t tag = (*desc)->getTag();
317                                                 if (!isaudio && !isvideo)
318                                                 {
319                                                         /* PES private can contain AC-3, DTS or lots of other stuff.
320                                                            check descriptors to get the exakt type. */
321                                                         switch (tag)
322                                                         {
323                                                         case 0x1C: // TS_PSI_DT_MPEG4_Audio
324                                                         case 0x2B: // TS_PSI_DT_MPEG2_AAC
325                                                         case AAC_DESCRIPTOR:
326                                                         case AC3_DESCRIPTOR:
327                                                         case DTS_DESCRIPTOR:
328                                                         case AUDIO_STREAM_DESCRIPTOR:
329                                                                 isaudio = 1;
330                                                                 break;
331                                                         case 0x28: // TS_PSI_DT_AVC
332                                                         case 0x1B: // TS_PSI_DT_MPEG4_Video
333                                                         case VIDEO_STREAM_DESCRIPTOR:
334                                                                 isvideo = 1;
335                                                                 break;
336                                                         case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
337                                                         {
338                                                                 /* libdvbsi++ doesn't yet support this descriptor type, so work around. */
339                                                                 if ((*desc)->getLength() < 4)
340                                                                         break;
341                                                                 unsigned char descr[6];
342                                                                 (*desc)->writeToBuffer(descr);
343                                                                 int format_identifier = (descr[2] << 24) | (descr[3] << 16) | (descr[4] << 8) | (descr[5]);
344                                                                 switch (format_identifier)
345                                                                 {
346                                                                 case 0x41432d33: // == 'AC-3'
347                                                                 case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
348                                                                 case 0x42535344: // == 'BSSD' (LPCM)
349                                                                         isaudio = 1;
350                                                                         break;
351                                                                 case 0x56432d31: // == 'VC-1'
352                                                                         isvideo = 1;
353                                                                         break;
354                                                                 default:
355                                                                         break;
356                                                                 }
357                                                         }
358                                                         default:
359                                                                 break;
360                                                         }
361                                                 }
362                                                 if (tag == CA_DESCRIPTOR)
363                                                         is_scrambled = 1;
364                                         }
365                                         break;
366                                 }
367                                 if (isaudio)
368                                         have_audio = true;
369                                 else if (isvideo)
370                                         have_video = true;
371                                 else
372                                         continue;
373                                 if (is_scrambled)
374                                         scrambled = true;
375                         }
376                         for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
377                                 desc != pmt.getDescriptors()->end(); ++desc)
378                         {
379                                 if ((*desc)->getTag() == CA_DESCRIPTOR)
380                                         scrambled = true;
381                         }
382                 }
383                 m_pmt_in_progress->second.scrambled = scrambled;
384                 if ( have_video )
385                         m_pmt_in_progress->second.serviceType = 1;
386                 else if ( have_audio )
387                         m_pmt_in_progress->second.serviceType = 2;
388                 else
389                         m_pmt_in_progress->second.serviceType = 100;
390         }
391         if (err == -1) // timeout or removed by sdt
392                 m_pmts_to_read.erase(m_pmt_in_progress++);
393         else if (m_pmt_running)
394                 ++m_pmt_in_progress;
395         else
396         {
397                 m_pmt_in_progress = m_pmts_to_read.begin();
398                 m_pmt_running = true;
399         }
400
401         if (m_pmt_in_progress != m_pmts_to_read.end())
402                 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
403         else
404         {
405                 m_PMT = 0;
406                 m_pmt_running = false;
407                 channelDone();
408         }
409 }
410
411
412 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
413 {
414                 /* add it to the list of known channels. */
415         if (chid)
416                 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
417 }
418
419 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
420 {
421                 /* check if we don't already have that channel ... */
422
423         int type;
424         feparm->getSystem(type);
425
426         switch(type)
427         {
428         case iDVBFrontend::feSatellite:
429         {
430                 eDVBFrontendParametersSatellite parm;
431                 feparm->getDVBS(parm);
432                 SCAN_eDebug("try to add %d %d %d %d %d %d",
433                         parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
434                 break;
435         }
436         case iDVBFrontend::feCable:
437         {
438                 eDVBFrontendParametersCable parm;
439                 feparm->getDVBC(parm);
440                 SCAN_eDebug("try to add %d %d %d %d",
441                         parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
442                 break;
443         }
444         case iDVBFrontend::feTerrestrial:
445         {
446                 eDVBFrontendParametersTerrestrial parm;
447                 feparm->getDVBT(parm);
448                 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
449                         parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
450                         parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
451                 break;
452         }
453         }
454
455         int found_count=0;
456                 /* ... in the list of channels to scan */
457         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
458         {
459                 if (sameChannel(*i, feparm))
460                 {
461                         if (!found_count)
462                         {
463                                 *i = feparm;  // update
464                                 SCAN_eDebug("update");
465                         }
466                         else
467                         {
468                                 SCAN_eDebug("remove dupe");
469                                 m_ch_toScan.erase(i++);
470                                 continue;
471                         }
472                         ++found_count;
473                 }
474                 ++i;
475         }
476
477         if (found_count > 0)
478         {
479                 SCAN_eDebug("already in todo list");
480                 return;
481         }
482
483                 /* ... in the list of successfully scanned channels */
484         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
485                 if (sameChannel(*i, feparm))
486                 {
487                         SCAN_eDebug("successfully scanned");
488                         return;
489                 }
490
491                 /* ... in the list of unavailable channels */
492         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
493                 if (sameChannel(*i, feparm, true))
494                 {
495                         SCAN_eDebug("scanned but not available");
496                         return;
497                 }
498
499                 /* ... on the current channel */
500         if (sameChannel(m_ch_current, feparm))
501         {
502                 SCAN_eDebug("is current");
503                 return;
504         }
505
506         SCAN_eDebug("really add");
507                 /* otherwise, add it to the todo list. */
508         m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
509 }
510
511 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
512 {
513         int diff;
514         if (ch1->calculateDifference(ch2, diff, exact))
515                 return 0;
516         if (diff < 4000) // more than 4mhz difference?
517                 return 1;
518         return 0;
519 }
520
521 void eDVBScan::channelDone()
522 {
523         if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
524         {
525                 unsigned long hash = 0;
526
527                 m_ch_current->getHash(hash);
528                 
529                 eDVBNamespace dvbnamespace = buildNamespace(
530                         (**m_SDT->getSections().begin()).getOriginalNetworkId(),
531                         (**m_SDT->getSections().begin()).getTransportStreamId(),
532                         hash);
533                 
534                 SCAN_eDebug("SDT: ");
535                 std::vector<ServiceDescriptionSection*>::const_iterator i;
536                 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
537                         processSDT(dvbnamespace, **i);
538                 m_ready &= ~validSDT;
539         }
540         
541         if (m_ready & validNIT)
542         {
543                 int system;
544                 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
545                 m_ch_current->getSystem(system);
546                 SCAN_eDebug("dumping NIT");
547                 if (m_flags & clearToScanOnFirstNIT)
548                 {
549                         m_ch_toScan_backup = m_ch_toScan;
550                         m_ch_toScan.clear();
551                 }
552                 std::vector<NetworkInformationSection*>::const_iterator i;
553                 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
554                 {
555                         const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
556                         
557                         for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin()); 
558                                 tsinfo != tsinfovec.end(); ++tsinfo)
559                         {
560                                 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
561                                         (*tsinfo)->getOriginalNetworkId());
562                                 
563                                 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
564                                 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
565                                 
566                                 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
567                                                 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
568                                 {
569                                         switch ((*desc)->getTag())
570                                         {
571                                         case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
572                                         {
573                                                 if (system != iDVBFrontend::feCable)
574                                                         break; // when current locked transponder is no cable transponder ignore this descriptor
575                                                 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
576                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
577                                                 eDVBFrontendParametersCable cable;
578                                                 cable.set(d);
579                                                 feparm->setDVBC(cable);
580
581                                                 unsigned long hash=0;
582                                                 feparm->getHash(hash);
583                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
584
585                                                 addChannelToScan(
586                                                         eDVBChannelID(ns, tsid, onid),
587                                                         feparm);
588                                                 break;
589                                         }
590                                         case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
591                                         {
592                                                 if (system != iDVBFrontend::feTerrestrial)
593                                                         break; // when current locked transponder is no terrestrial transponder ignore this descriptor
594                                                 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
595                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
596                                                 eDVBFrontendParametersTerrestrial terr;
597                                                 terr.set(d);
598                                                 feparm->setDVBT(terr);
599
600                                                 unsigned long hash=0;
601                                                 feparm->getHash(hash);
602                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
603
604                                                 addChannelToScan(
605                                                         eDVBChannelID(ns, tsid, onid),
606                                                         feparm);
607                                                 break;
608                                         }
609                                         case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
610                                         {
611                                                 if (system != iDVBFrontend::feSatellite)
612                                                         break; // when current locked transponder is no satellite transponder ignore this descriptor
613
614                                                 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
615                                                 if (d.getFrequency() < 10000)
616                                                         break;
617                                                 
618                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
619                                                 eDVBFrontendParametersSatellite sat;
620                                                 sat.set(d);
621
622                                                 eDVBFrontendParametersSatellite p;
623                                                 m_ch_current->getDVBS(p);
624
625                                                 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
626                                                         sat.orbital_position = p.orbital_position;
627
628                                                 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
629                                                 {
630                                                         SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
631                                                         sat.orbital_position = p.orbital_position;
632                                                 }
633
634                                                 feparm->setDVBS(sat);
635
636                                                 if ( p.orbital_position != sat.orbital_position)
637                                                         SCAN_eDebug("dropping this transponder, it's on another satellite.");
638                                                 else
639                                                 {
640                                                         unsigned long hash=0;
641                                                         feparm->getHash(hash);
642                                                         addChannelToScan(
643                                                                         eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
644                                                                         feparm);
645                                                 }
646                                                 break;
647                                         }
648                                         default:
649                                                 SCAN_eDebug("descr<%x>", (*desc)->getTag());
650                                                 break;
651                                         }
652                                 }
653                         }
654                         
655                 }
656
657                         /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
658                            no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
659                            has been found.
660
661                            This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
662                         */
663                 if (m_flags & clearToScanOnFirstNIT)
664                 {
665                         if (m_ch_toScan.empty())
666                         {
667                                 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
668                                 m_ch_toScan = m_ch_toScan_backup;
669                         } else
670                                 m_flags &= ~clearToScanOnFirstNIT;
671                 }
672                 m_ready &= ~validNIT;
673         }
674
675         if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
676         {
677                 if (m_abort_current_pmt)
678                 {
679                         m_abort_current_pmt = false;
680                         PMTready(-1);
681                 }
682                 return;
683         }
684
685         SCAN_eDebug("channel done!");
686         
687                 /* if we had services on this channel, we declare
688                    this channels as "known good". add it.
689                    
690                    (TODO: not yet implemented)
691                    a NIT entry could have possible overridden
692                    our frontend data with more exact data.
693                    
694                    (TODO: not yet implemented)
695                    the tuning process could have lead to more
696                    exact data than the user entered.
697                    
698                    The channel id was probably corrected
699                    by the data written in the SDT. this is
700                    important, as "initial transponder lists"
701                    usually don't have valid CHIDs (and that's
702                    good).
703                    
704                    These are the reasons for adding the transponder
705                    here, and not before.
706                 */
707
708         for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
709         {
710                 int type;
711                 eServiceReferenceDVB ref;
712                 ePtr<eDVBService> service = new eDVBService;
713
714                 if (!m_chid_current)
715                 {
716                         unsigned long hash = 0;
717
718                         m_ch_current->getHash(hash);
719
720                         m_chid_current = eDVBChannelID(
721                                 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
722                                 m_pat_tsid, eOriginalNetworkID(0));
723                 }
724
725                 if (m_pmt_in_progress->second.serviceType == 1)
726                         SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
727                 else if (m_pmt_in_progress->second.serviceType == 2)
728                         SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
729                 else
730                         SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
731
732                 ref.set(m_chid_current);
733                 ref.setServiceID(m_pmt_in_progress->first);
734                 ref.setServiceType(m_pmt_in_progress->second.serviceType);
735
736                 if (!m_ch_current->getSystem(type))
737                 {
738                         char sname[255];
739                         char pname[255];
740                         memset(pname, 0, sizeof(pname));
741                         memset(sname, 0, sizeof(sname));
742                         switch(type)
743                         {
744                                 case iDVBFrontend::feSatellite:
745                                 {
746                                         eDVBFrontendParametersSatellite parm;
747                                         m_ch_current->getDVBS(parm);
748                                         snprintf(sname, 255, "%d%c SID 0x%02x",
749                                                         parm.frequency/1000,
750                                                         parm.polarisation ? 'V' : 'H',
751                                                         m_pmt_in_progress->first);
752                                         snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
753                                                 parm.system ? "DVB-S2" : "DVB-S",
754                                                 parm.modulation == 1 ? "QPSK" : "8PSK",
755                                                 parm.frequency/1000,
756                                                 parm.polarisation ? 'V' : 'H',
757                                                 parm.orbital_position/10,
758                                                 parm.orbital_position%10,
759                                                 parm.orbital_position > 0 ? 'E' : 'W');
760                                         break;
761                                 }
762                                 case iDVBFrontend::feTerrestrial:
763                                 {
764                                         ePtr<iDVBFrontend> fe;
765                                         eDVBFrontendParametersTerrestrial parm;
766                                         m_ch_current->getDVBT(parm);
767                                         snprintf(sname, 255, "%d SID 0x%02x",
768                                                 parm.frequency/1000,
769                                                 m_pmt_in_progress->first);
770                                         if (!m_channel->getFrontend(fe))
771                                         {
772                                                 ePyObject tp_dict = PyDict_New();
773                                                 fe->getTransponderData(tp_dict, false);
774                                                 m_corrected_frequencys[m_chid_current] =
775                                                         PyInt_AsLong(PyDict_GetItemString(tp_dict, "frequency"));
776                                                 Py_DECREF(tp_dict);
777                                         }
778                                         break;
779                                 }
780                                 case iDVBFrontend::feCable:
781                                 {
782                                         eDVBFrontendParametersCable parm;
783                                         m_ch_current->getDVBC(parm);
784                                         snprintf(sname, 255, "%d SID 0x%02x",
785                                                 parm.frequency/1000,
786                                                 m_pmt_in_progress->first);
787                                         break;
788                                 }
789                         }
790                         SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
791                         service->m_service_name = convertDVBUTF8(sname);
792                         service->genSortName();
793                         service->m_provider_name = convertDVBUTF8(pname);
794                 }
795
796                 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
797                         SCAN_eDebug("add not scrambled!");
798                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
799                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
800                         if (i.second)
801                         {
802                                 m_last_service = i.first;
803                                 m_event(evtNewService);
804                         }
805                 }
806                 else
807                         SCAN_eDebug("dont add... is scrambled!");
808                 m_pmts_to_read.erase(m_pmt_in_progress++);
809         }
810
811         if (!m_chid_current)
812                 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
813         else
814                 addKnownGoodChannel(m_chid_current, m_ch_current);
815         
816         m_ch_scanned.push_back(m_ch_current);
817         
818         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
819         {
820                 if (sameChannel(*i, m_ch_current))
821                 {
822                         SCAN_eDebug("remove dupe 2");
823                         m_ch_toScan.erase(i++);
824                         continue;
825                 }
826                 ++i;
827         }
828         
829         nextChannel();
830 }
831
832 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
833 {
834         m_flags = flags;
835         m_ch_toScan.clear();
836         m_ch_scanned.clear();
837         m_ch_unavailable.clear();
838         m_new_channels.clear();
839         m_new_services.clear();
840         m_last_service = m_new_services.end();
841
842         for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
843         {
844                 bool exist=false;
845                 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
846                 {
847                         if (sameChannel(*i, *ii, true))
848                         {
849                                 exist=true;
850                                 break;
851                         }
852                 }
853                 if (!exist)
854                         m_ch_toScan.push_back(*i);
855         }
856
857         nextChannel();
858 }
859
860 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
861 {
862         if (m_flags & scanRemoveServices)
863         {
864                 bool clearTerrestrial=false;
865                 bool clearCable=false;
866                 std::set<unsigned int> scanned_sat_positions;
867                 
868                 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
869                 for (;it != m_ch_scanned.end(); ++it)
870                 {
871                         if (m_flags & scanDontRemoveUnscanned)
872                                 db->removeServices(&(*(*it)));
873                         else
874                         {
875                                 int system;
876                                 (*it)->getSystem(system);
877                                 switch(system)
878                                 {
879                                         case iDVBFrontend::feSatellite:
880                                         {
881                                                 eDVBFrontendParametersSatellite sat_parm;
882                                                 (*it)->getDVBS(sat_parm);
883                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
884                                                 break;
885                                         }
886                                         case iDVBFrontend::feTerrestrial:
887                                         {
888                                                 clearTerrestrial=true;
889                                                 break;
890                                         }
891                                         case iDVBFrontend::feCable:
892                                         {
893                                                 clearCable=true;
894                                                 break;
895                                         }
896                                 }
897                         }
898                 }
899
900                 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
901                 {
902                         if (m_flags & scanDontRemoveUnscanned)
903                                 db->removeServices(&(*(*it)));
904                         else
905                         {
906                                 int system;
907                                 (*it)->getSystem(system);
908                                 switch(system)
909                                 {
910                                         case iDVBFrontend::feSatellite:
911                                         {
912                                                 eDVBFrontendParametersSatellite sat_parm;
913                                                 (*it)->getDVBS(sat_parm);
914                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
915                                                 break;
916                                         }
917                                         case iDVBFrontend::feTerrestrial:
918                                         {
919                                                 clearTerrestrial=true;
920                                                 break;
921                                         }
922                                         case iDVBFrontend::feCable:
923                                         {
924                                                 clearCable=true;
925                                                 break;
926                                         }
927                                 }
928                         }
929                 }
930
931                 if (clearTerrestrial)
932                 {
933                         eDVBChannelID chid;
934                         chid.dvbnamespace=0xEEEE0000;
935                         db->removeServices(chid);
936                 }
937                 if (clearCable)
938                 {
939                         eDVBChannelID chid;
940                         chid.dvbnamespace=0xFFFF0000;
941                         db->removeServices(chid);
942                 }
943                 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
944                 {
945                         eDVBChannelID chid;
946                         if (m_flags & scanDontRemoveFeeds)
947                                 chid.dvbnamespace = eDVBNamespace((*x)<<16);
948 //                      eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
949                         db->removeServices(chid, *x);
950                 }
951         }
952
953         for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator 
954                         ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
955         {
956                 int system;
957                 ch->second->getSystem(system);
958                 if (system == iDVBFrontend::feTerrestrial)
959                 {
960                         std::map<eDVBChannelID, unsigned int>::iterator it = m_corrected_frequencys.find(ch->first);
961                         if (it != m_corrected_frequencys.end())
962                         {
963                                 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
964                                 eDVBFrontendParametersTerrestrial parm;
965                                 p->getDVBT(parm);
966                                 eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
967                                         ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
968                                         ch->first.dvbnamespace.get(), it->second, parm.frequency);
969                                 parm.frequency = it->second;
970                                 p->setDVBT(parm);
971                                 m_corrected_frequencys.erase(it);
972                         }
973                 }
974                 if (m_flags & scanOnlyFree)
975                 {
976                         eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
977                         ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
978                 }
979                 db->addChannelToList(ch->first, ch->second);
980         }
981
982         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
983                 service(m_new_services.begin()); service != m_new_services.end(); ++service)
984         {
985                 ePtr<eDVBService> dvb_service;
986                 if (!db->getService(service->first, dvb_service))
987                 {
988                         if (dvb_service->m_flags & eDVBService::dxNoSDT)
989                                 continue;
990                         if (!(dvb_service->m_flags & eDVBService::dxHoldName))
991                         {
992                                 dvb_service->m_service_name = service->second->m_service_name;
993                                 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
994                         }
995                         dvb_service->m_provider_name = service->second->m_provider_name;
996                         if (service->second->m_ca.size())
997                                 dvb_service->m_ca = service->second->m_ca;
998                         if (!dontRemoveOldFlags) // do not remove new found flags when not wished
999                                 dvb_service->m_flags &= ~eDVBService::dxNewFound;
1000                 }
1001                 else
1002                 {
1003                         db->addService(service->first, service->second);
1004                         if (!(m_flags & scanRemoveServices))
1005                                 service->second->m_flags |= eDVBService::dxNewFound;
1006                 }
1007         }
1008 }
1009
1010 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
1011 {
1012         const ServiceDescriptionList &services = *sdt.getDescriptions();
1013         SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
1014         eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
1015         
1016         /* save correct CHID for this channel */
1017         m_chid_current = chid;
1018
1019         for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1020         {
1021                 unsigned short service_id = (*s)->getServiceId();
1022                 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1023                 bool add = true;
1024
1025                 if (m_flags & scanOnlyFree)
1026                 {
1027                         std::map<unsigned short, service>::iterator it =
1028                                 m_pmts_to_read.find(service_id);
1029                         if (it != m_pmts_to_read.end())
1030                         {
1031                                 if (it->second.scrambled)
1032                                 {
1033                                         SCAN_eDebug("is scrambled!");
1034                                         add = false;
1035                                 }
1036                                 else
1037                                         SCAN_eDebug("is free");
1038                         }
1039                         else {
1040                                 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1041                                 add = false;
1042                         }
1043                 }
1044
1045                 if (add)
1046                 {
1047                         eServiceReferenceDVB ref;
1048                         ePtr<eDVBService> service = new eDVBService;
1049
1050                         ref.set(chid);
1051                         ref.setServiceID(service_id);
1052
1053                         for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1054                                         desc != (*s)->getDescriptors()->end(); ++desc)
1055                         {
1056                                 switch ((*desc)->getTag())
1057                                 {
1058                                 case SERVICE_DESCRIPTOR:
1059                                 {
1060                                         ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1061                                         ref.setServiceType(d.getServiceType());
1062                                         service->m_service_name = convertDVBUTF8(d.getServiceName());
1063                                         service->genSortName();
1064
1065                                         service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1066                                         SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1067                                         break;
1068                                 }
1069                                 case CA_IDENTIFIER_DESCRIPTOR:
1070                                 {
1071                                         CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1072                                         const CaSystemIdList &caids = *d.getCaSystemIds();
1073                                         SCAN_eDebugNoNewLine("CA ");
1074                                         for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1075                                         {
1076                                                 SCAN_eDebugNoNewLine("%04x ", *i);
1077                                                 service->m_ca.push_front(*i);
1078                                         }
1079                                         SCAN_eDebug("");
1080                                         break;
1081                                 }
1082                                 default:
1083                                         SCAN_eDebug("descr<%x>", (*desc)->getTag());
1084                                         break;
1085                                 }
1086                         }
1087
1088                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1089                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1090
1091                         if (i.second)
1092                         {
1093                                 m_last_service = i.first;
1094                                 m_event(evtNewService);
1095                         }
1096                 }
1097                 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1098                         m_abort_current_pmt = true;
1099                 else
1100                         m_pmts_to_read.erase(service_id);
1101         }
1102
1103         return 0;
1104 }
1105
1106 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1107 {
1108         connection = new eConnection(this, m_event.connect(event));
1109         return 0;
1110 }
1111
1112 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1113 {
1114         transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1115         transponders_total = m_ch_toScan.size() + transponders_done;
1116         services = m_new_services.size();
1117 }
1118
1119 void eDVBScan::getLastServiceName(std::string &last_service_name)
1120 {
1121         if (m_last_service == m_new_services.end())
1122                 last_service_name = "";
1123         else
1124                 last_service_name = m_last_service->second->m_service_name;
1125 }
1126
1127 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1128 {
1129         if (m_channel)
1130                 return m_channel->getFrontend(fe);
1131         fe = 0;
1132         return -1;
1133 }
1134
1135 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)
1136 {
1137         if (m_ch_current)
1138         {
1139                 tp = m_ch_current;
1140                 return 0;
1141         }
1142         tp = 0;
1143         return -1;
1144 }