patch by Dr.Best - allow using filesize of movie in converter
[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 #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                 for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
285                 {
286                         const ProgramMapSection &pmt = **i;
287                         if (pcrpid == 0xFFFF)
288                                 pcrpid = pmt.getPcrPid();
289                         else
290                                 SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
291                         ElementaryStreamInfoConstIterator es;
292                         for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
293                         {
294                                 int isaudio = 0, isvideo = 0, is_scrambled = 0;
295                                 switch ((*es)->getType())
296                                 {
297                                 case 0x1b: // AVC Video Stream (MPEG4 H264)
298                                 case 0x01: // MPEG 1 video
299                                 case 0x02: // MPEG 2 video
300                                         isvideo = 1;
301                                         //break; fall through !!!
302                                 case 0x03: // MPEG 1 audio
303                                 case 0x04: // MPEG 2 audio:
304                                         if (!isvideo)
305                                                 isaudio = 1;
306                                         //break; fall through !!!
307                                 case 0x06: // PES Private
308                                 case 0x81: // user private
309                                                 /* PES private can contain AC-3, DTS or lots of other stuff.
310                                                    check descriptors to get the exact type. */
311                                         for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
312                                                         desc != (*es)->getDescriptors()->end(); ++desc)
313                                         {
314                                                 uint8_t tag = (*desc)->getTag();
315                                                 if (!isaudio && !isvideo)
316                                                 {
317                                                         switch (tag)
318                                                         {
319                                                         case DTS_DESCRIPTOR:
320                                                         case AAC_DESCRIPTOR:
321                                                         case AC3_DESCRIPTOR:
322                                                                 isaudio = 1;
323                                                                 break;
324                                                         case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
325                                                         {
326                                                                         /* libdvbsi++ doesn't yet support this descriptor type, so work around. */
327                                                                 if ((*desc)->getLength() != 4)
328                                                                         break;
329                                                                 unsigned char descr[6];
330                                                                 (*desc)->writeToBuffer(descr);
331                                                                 int format_identifier = (descr[2] << 24) | (descr[3] << 16) | (descr[4] << 8) | (descr[5]);
332                                                                 switch (format_identifier)
333                                                                 {
334                                                                 case 0x41432d33:
335                                                                         isaudio = 1;
336                                                                 default:
337                                                                         break;
338                                                                 }
339                                                                 break;
340                                                         }
341                                                         }
342                                                 }
343                                                 if (tag == CA_DESCRIPTOR)
344                                                         is_scrambled = 1;
345                                         }
346                                         break;
347                                 }
348                                 if (isaudio)
349                                         have_audio = true;
350                                 else if (isvideo)
351                                         have_video = true;
352                                 else
353                                         continue;
354                                 if (is_scrambled)
355                                         scrambled = true;
356                         }
357                         for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
358                                 desc != pmt.getDescriptors()->end(); ++desc)
359                         {
360                                 if ((*desc)->getTag() == CA_DESCRIPTOR)
361                                         scrambled = true;
362                         }
363                 }
364                 m_pmt_in_progress->second.scrambled = scrambled;
365                 if ( have_video )
366                         m_pmt_in_progress->second.serviceType = 1;
367                 else if ( have_audio )
368                         m_pmt_in_progress->second.serviceType = 2;
369                 else
370                         m_pmt_in_progress->second.serviceType = 100;
371         }
372         if (err == -1) // timeout or removed by sdt
373                 m_pmts_to_read.erase(m_pmt_in_progress++);
374         else if (m_pmt_running)
375                 ++m_pmt_in_progress;
376         else
377         {
378                 m_pmt_in_progress = m_pmts_to_read.begin();
379                 m_pmt_running = true;
380         }
381
382         if (m_pmt_in_progress != m_pmts_to_read.end())
383                 m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
384         else
385         {
386                 m_PMT = 0;
387                 m_pmt_running = false;
388                 channelDone();
389         }
390 }
391
392
393 void eDVBScan::addKnownGoodChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
394 {
395                 /* add it to the list of known channels. */
396         if (chid)
397                 m_new_channels.insert(std::pair<eDVBChannelID,ePtr<iDVBFrontendParameters> >(chid, feparm));
398 }
399
400 void eDVBScan::addChannelToScan(const eDVBChannelID &chid, iDVBFrontendParameters *feparm)
401 {
402                 /* check if we don't already have that channel ... */
403
404         int type;
405         feparm->getSystem(type);
406
407         switch(type)
408         {
409         case iDVBFrontend::feSatellite:
410         {
411                 eDVBFrontendParametersSatellite parm;
412                 feparm->getDVBS(parm);
413                 SCAN_eDebug("try to add %d %d %d %d %d %d",
414                         parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
415                 break;
416         }
417         case iDVBFrontend::feCable:
418         {
419                 eDVBFrontendParametersCable parm;
420                 feparm->getDVBC(parm);
421                 SCAN_eDebug("try to add %d %d %d %d",
422                         parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
423                 break;
424         }
425         case iDVBFrontend::feTerrestrial:
426         {
427                 eDVBFrontendParametersTerrestrial parm;
428                 feparm->getDVBT(parm);
429                 SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
430                         parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
431                         parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
432                 break;
433         }
434         }
435
436         int found_count=0;
437                 /* ... in the list of channels to scan */
438         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
439         {
440                 if (sameChannel(*i, feparm))
441                 {
442                         if (!found_count)
443                         {
444                                 *i = feparm;  // update
445                                 SCAN_eDebug("update");
446                         }
447                         else
448                         {
449                                 SCAN_eDebug("remove dupe");
450                                 m_ch_toScan.erase(i++);
451                                 continue;
452                         }
453                         ++found_count;
454                 }
455                 ++i;
456         }
457
458         if (found_count > 0)
459         {
460                 SCAN_eDebug("already in todo list");
461                 return;
462         }
463
464                 /* ... in the list of successfully scanned channels */
465         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
466                 if (sameChannel(*i, feparm))
467                 {
468                         SCAN_eDebug("successfully scanned");
469                         return;
470                 }
471
472                 /* ... in the list of unavailable channels */
473         for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
474                 if (sameChannel(*i, feparm, true))
475                 {
476                         SCAN_eDebug("scanned but not available");
477                         return;
478                 }
479
480                 /* ... on the current channel */
481         if (sameChannel(m_ch_current, feparm))
482         {
483                 SCAN_eDebug("is current");
484                 return;
485         }
486
487         SCAN_eDebug("really add");
488                 /* otherwise, add it to the todo list. */
489         m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
490 }
491
492 int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2, bool exact) const
493 {
494         int diff;
495         if (ch1->calculateDifference(ch2, diff, exact))
496                 return 0;
497         if (diff < 4000) // more than 4mhz difference?
498                 return 1;
499         return 0;
500 }
501
502 void eDVBScan::channelDone()
503 {
504         if (m_ready & validSDT && (!(m_flags & scanOnlyFree) || !m_pmt_running))
505         {
506                 unsigned long hash = 0;
507
508                 m_ch_current->getHash(hash);
509                 
510                 eDVBNamespace dvbnamespace = buildNamespace(
511                         (**m_SDT->getSections().begin()).getOriginalNetworkId(),
512                         (**m_SDT->getSections().begin()).getTransportStreamId(),
513                         hash);
514                 
515                 SCAN_eDebug("SDT: ");
516                 std::vector<ServiceDescriptionSection*>::const_iterator i;
517                 for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
518                         processSDT(dvbnamespace, **i);
519                 m_ready &= ~validSDT;
520         }
521         
522         if (m_ready & validNIT)
523         {
524                 int system;
525                 std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
526                 m_ch_current->getSystem(system);
527                 SCAN_eDebug("dumping NIT");
528                 if (m_flags & clearToScanOnFirstNIT)
529                 {
530                         m_ch_toScan_backup = m_ch_toScan;
531                         m_ch_toScan.clear();
532                 }
533                 std::vector<NetworkInformationSection*>::const_iterator i;
534                 for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i)
535                 {
536                         const TransportStreamInfoList &tsinfovec = *(*i)->getTsInfo();
537                         
538                         for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin()); 
539                                 tsinfo != tsinfovec.end(); ++tsinfo)
540                         {
541                                 SCAN_eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(),
542                                         (*tsinfo)->getOriginalNetworkId());
543                                 
544                                 eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
545                                 eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
546                                 
547                                 for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
548                                                 desc != (*tsinfo)->getDescriptors()->end(); ++desc)
549                                 {
550                                         switch ((*desc)->getTag())
551                                         {
552                                         case CABLE_DELIVERY_SYSTEM_DESCRIPTOR:
553                                         {
554                                                 if (system != iDVBFrontend::feCable)
555                                                         break; // when current locked transponder is no cable transponder ignore this descriptor
556                                                 CableDeliverySystemDescriptor &d = (CableDeliverySystemDescriptor&)**desc;
557                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
558                                                 eDVBFrontendParametersCable cable;
559                                                 cable.set(d);
560                                                 feparm->setDVBC(cable);
561
562                                                 unsigned long hash=0;
563                                                 feparm->getHash(hash);
564                                                 eDVBNamespace ns = buildNamespace(onid, tsid, hash);
565
566                                                 addChannelToScan(
567                                                         eDVBChannelID(ns, tsid, onid),
568                                                         feparm);
569                                                 break;
570                                         }
571                                         case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
572                                         {
573                                                 if (system != iDVBFrontend::feTerrestrial)
574                                                         break; // when current locked transponder is no terrestrial transponder ignore this descriptor
575                                                 TerrestrialDeliverySystemDescriptor &d = (TerrestrialDeliverySystemDescriptor&)**desc;
576                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
577                                                 eDVBFrontendParametersTerrestrial terr;
578                                                 terr.set(d);
579                                                 feparm->setDVBT(terr);
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 SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
591                                         {
592                                                 if (system != iDVBFrontend::feSatellite)
593                                                         break; // when current locked transponder is no satellite transponder ignore this descriptor
594
595                                                 SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc;
596                                                 if (d.getFrequency() < 10000)
597                                                         break;
598                                                 
599                                                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
600                                                 eDVBFrontendParametersSatellite sat;
601                                                 sat.set(d);
602
603                                                 eDVBFrontendParametersSatellite p;
604                                                 m_ch_current->getDVBS(p);
605
606                                                 if ( abs(p.orbital_position - sat.orbital_position) < 5 )
607                                                         sat.orbital_position = p.orbital_position;
608
609                                                 if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
610                                                 {
611                                                         SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
612                                                         sat.orbital_position = p.orbital_position;
613                                                 }
614
615                                                 feparm->setDVBS(sat);
616
617                                                 if ( p.orbital_position != sat.orbital_position)
618                                                         SCAN_eDebug("dropping this transponder, it's on another satellite.");
619                                                 else
620                                                 {
621                                                         unsigned long hash=0;
622                                                         feparm->getHash(hash);
623                                                         addChannelToScan(
624                                                                         eDVBChannelID(buildNamespace(onid, tsid, hash), tsid, onid),
625                                                                         feparm);
626                                                 }
627                                                 break;
628                                         }
629                                         default:
630                                                 SCAN_eDebug("descr<%x>", (*desc)->getTag());
631                                                 break;
632                                         }
633                                 }
634                         }
635                         
636                 }
637
638                         /* a pitfall is to have the clearToScanOnFirstNIT-flag set, and having channels which have
639                            no or invalid NIT. this code will not erase the toScan list unless at least one valid entry
640                            has been found.
641
642                            This is not a perfect solution, as the channel could contain a partial NIT. Life's bad.
643                         */
644                 if (m_flags & clearToScanOnFirstNIT)
645                 {
646                         if (m_ch_toScan.empty())
647                         {
648                                 eWarning("clearToScanOnFirstNIT was set, but NIT is invalid. Refusing to stop scan.");
649                                 m_ch_toScan = m_ch_toScan_backup;
650                         } else
651                                 m_flags &= ~clearToScanOnFirstNIT;
652                 }
653                 m_ready &= ~validNIT;
654         }
655
656         if (m_pmt_running || (m_ready & m_ready_all) != m_ready_all)
657         {
658                 if (m_abort_current_pmt)
659                 {
660                         m_abort_current_pmt = false;
661                         PMTready(-1);
662                 }
663                 return;
664         }
665
666         SCAN_eDebug("channel done!");
667         
668                 /* if we had services on this channel, we declare
669                    this channels as "known good". add it.
670                    
671                    (TODO: not yet implemented)
672                    a NIT entry could have possible overridden
673                    our frontend data with more exact data.
674                    
675                    (TODO: not yet implemented)
676                    the tuning process could have lead to more
677                    exact data than the user entered.
678                    
679                    The channel id was probably corrected
680                    by the data written in the SDT. this is
681                    important, as "initial transponder lists"
682                    usually don't have valid CHIDs (and that's
683                    good).
684                    
685                    These are the reasons for adding the transponder
686                    here, and not before.
687                 */
688
689         for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
690         {
691                 int type;
692                 eServiceReferenceDVB ref;
693                 ePtr<eDVBService> service = new eDVBService;
694
695                 if (!m_chid_current)
696                 {
697                         unsigned long hash = 0;
698
699                         m_ch_current->getHash(hash);
700
701                         m_chid_current = eDVBChannelID(
702                                 buildNamespace(eOriginalNetworkID(0), m_pat_tsid, hash),
703                                 m_pat_tsid, eOriginalNetworkID(0));
704                 }
705
706                 if (m_pmt_in_progress->second.serviceType == 1)
707                         SCAN_eDebug("SID %04x is VIDEO", m_pmt_in_progress->first);
708                 else if (m_pmt_in_progress->second.serviceType == 2)
709                         SCAN_eDebug("SID %04x is AUDIO", m_pmt_in_progress->first);
710                 else
711                         SCAN_eDebug("SID %04x is DATA", m_pmt_in_progress->first);
712
713                 ref.set(m_chid_current);
714                 ref.setServiceID(m_pmt_in_progress->first);
715                 ref.setServiceType(m_pmt_in_progress->second.serviceType);
716
717                 if (!m_ch_current->getSystem(type))
718                 {
719                         char sname[255];
720                         char pname[255];
721                         memset(pname, 0, sizeof(pname));
722                         memset(sname, 0, sizeof(sname));
723                         switch(type)
724                         {
725                                 case iDVBFrontend::feSatellite:
726                                 {
727                                         eDVBFrontendParametersSatellite parm;
728                                         m_ch_current->getDVBS(parm);
729                                         snprintf(sname, 255, "%d%c SID 0x%02x",
730                                                         parm.frequency/1000,
731                                                         parm.polarisation ? 'V' : 'H',
732                                                         m_pmt_in_progress->first);
733                                         snprintf(pname, 255, "%s %s %d%c %d.%d°%c",
734                                                 parm.system ? "DVB-S2" : "DVB-S",
735                                                 parm.modulation == 1 ? "QPSK" : "8PSK",
736                                                 parm.frequency/1000,
737                                                 parm.polarisation ? 'V' : 'H',
738                                                 parm.orbital_position/10,
739                                                 parm.orbital_position%10,
740                                                 parm.orbital_position > 0 ? 'E' : 'W');
741                                         break;
742                                 }
743                                 case iDVBFrontend::feTerrestrial:
744                                 {
745                                         ePtr<iDVBFrontend> fe;
746                                         eDVBFrontendParametersTerrestrial parm;
747                                         m_ch_current->getDVBT(parm);
748                                         snprintf(sname, 255, "%d SID 0x%02x",
749                                                 parm.frequency/1000,
750                                                 m_pmt_in_progress->first);
751                                         if (!m_channel->getFrontend(fe))
752                                         {
753                                                 ePyObject tp_dict = PyDict_New();
754                                                 fe->getTransponderData(tp_dict, false);
755                                                 m_corrected_frequencys[m_chid_current] =
756                                                         PyInt_AsLong(PyDict_GetItemString(tp_dict, "frequency"));
757                                                 Py_DECREF(tp_dict);
758                                         }
759                                         break;
760                                 }
761                                 case iDVBFrontend::feCable:
762                                 {
763                                         eDVBFrontendParametersCable parm;
764                                         m_ch_current->getDVBC(parm);
765                                         snprintf(sname, 255, "%d SID 0x%02x",
766                                                 parm.frequency/1000,
767                                                 m_pmt_in_progress->first);
768                                         break;
769                                 }
770                         }
771                         SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
772                         service->m_service_name = convertDVBUTF8(sname);
773                         service->genSortName();
774                         service->m_provider_name = convertDVBUTF8(pname);
775                 }
776
777                 if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
778                         SCAN_eDebug("add not scrambled!");
779                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
780                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
781                         if (i.second)
782                         {
783                                 m_last_service = i.first;
784                                 m_event(evtNewService);
785                         }
786                 }
787                 else
788                         SCAN_eDebug("dont add... is scrambled!");
789                 m_pmts_to_read.erase(m_pmt_in_progress++);
790         }
791
792         if (!m_chid_current)
793                 eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
794         else
795                 addKnownGoodChannel(m_chid_current, m_ch_current);
796         
797         m_ch_scanned.push_back(m_ch_current);
798         
799         for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
800         {
801                 if (sameChannel(*i, m_ch_current))
802                 {
803                         SCAN_eDebug("remove dupe 2");
804                         m_ch_toScan.erase(i++);
805                         continue;
806                 }
807                 ++i;
808         }
809         
810         nextChannel();
811 }
812
813 void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transponders, int flags)
814 {
815         m_flags = flags;
816         m_ch_toScan.clear();
817         m_ch_scanned.clear();
818         m_ch_unavailable.clear();
819         m_new_channels.clear();
820         m_new_services.clear();
821         m_last_service = m_new_services.end();
822
823         for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
824         {
825                 bool exist=false;
826                 for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator ii(m_ch_toScan.begin()); ii != m_ch_toScan.end(); ++ii)
827                 {
828                         if (sameChannel(*i, *ii, true))
829                         {
830                                 exist=true;
831                                 break;
832                         }
833                 }
834                 if (!exist)
835                         m_ch_toScan.push_back(*i);
836         }
837
838         nextChannel();
839 }
840
841 void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
842 {
843         if (m_flags & scanRemoveServices)
844         {
845                 bool clearTerrestrial=false;
846                 bool clearCable=false;
847                 std::set<unsigned int> scanned_sat_positions;
848                 
849                 std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
850                 for (;it != m_ch_scanned.end(); ++it)
851                 {
852                         if (m_flags & scanDontRemoveUnscanned)
853                                 db->removeServices(&(*(*it)));
854                         else
855                         {
856                                 int system;
857                                 (*it)->getSystem(system);
858                                 switch(system)
859                                 {
860                                         case iDVBFrontend::feSatellite:
861                                         {
862                                                 eDVBFrontendParametersSatellite sat_parm;
863                                                 (*it)->getDVBS(sat_parm);
864                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
865                                                 break;
866                                         }
867                                         case iDVBFrontend::feTerrestrial:
868                                         {
869                                                 clearTerrestrial=true;
870                                                 break;
871                                         }
872                                         case iDVBFrontend::feCable:
873                                         {
874                                                 clearCable=true;
875                                                 break;
876                                         }
877                                 }
878                         }
879                 }
880
881                 for (it=m_ch_unavailable.begin();it != m_ch_unavailable.end(); ++it)
882                 {
883                         if (m_flags & scanDontRemoveUnscanned)
884                                 db->removeServices(&(*(*it)));
885                         else
886                         {
887                                 int system;
888                                 (*it)->getSystem(system);
889                                 switch(system)
890                                 {
891                                         case iDVBFrontend::feSatellite:
892                                         {
893                                                 eDVBFrontendParametersSatellite sat_parm;
894                                                 (*it)->getDVBS(sat_parm);
895                                                 scanned_sat_positions.insert(sat_parm.orbital_position);
896                                                 break;
897                                         }
898                                         case iDVBFrontend::feTerrestrial:
899                                         {
900                                                 clearTerrestrial=true;
901                                                 break;
902                                         }
903                                         case iDVBFrontend::feCable:
904                                         {
905                                                 clearCable=true;
906                                                 break;
907                                         }
908                                 }
909                         }
910                 }
911
912                 if (clearTerrestrial)
913                 {
914                         eDVBChannelID chid;
915                         chid.dvbnamespace=0xEEEE0000;
916                         db->removeServices(chid);
917                 }
918                 if (clearCable)
919                 {
920                         eDVBChannelID chid;
921                         chid.dvbnamespace=0xFFFF0000;
922                         db->removeServices(chid);
923                 }
924                 for (std::set<unsigned int>::iterator x(scanned_sat_positions.begin()); x != scanned_sat_positions.end(); ++x)
925                 {
926                         eDVBChannelID chid;
927                         if (m_flags & scanDontRemoveFeeds)
928                                 chid.dvbnamespace = eDVBNamespace((*x)<<16);
929 //                      eDebug("remove %d %08x", *x, chid.dvbnamespace.get());
930                         db->removeServices(chid, *x);
931                 }
932         }
933
934         for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator 
935                         ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
936         {
937                 int system;
938                 ch->second->getSystem(system);
939                 if (system == iDVBFrontend::feTerrestrial)
940                 {
941                         std::map<eDVBChannelID, unsigned int>::iterator it = m_corrected_frequencys.find(ch->first);
942                         if (it != m_corrected_frequencys.end())
943                         {
944                                 eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
945                                 eDVBFrontendParametersTerrestrial parm;
946                                 p->getDVBT(parm);
947                                 eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
948                                         ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
949                                         ch->first.dvbnamespace.get(), it->second, parm.frequency);
950                                 parm.frequency = it->second;
951                                 p->setDVBT(parm);
952                                 m_corrected_frequencys.erase(it);
953                         }
954                 }
955                 if (m_flags & scanOnlyFree)
956                 {
957                         eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
958                         ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
959                 }
960                 db->addChannelToList(ch->first, ch->second);
961         }
962
963         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::const_iterator
964                 service(m_new_services.begin()); service != m_new_services.end(); ++service)
965         {
966                 ePtr<eDVBService> dvb_service;
967                 if (!db->getService(service->first, dvb_service))
968                 {
969                         if (dvb_service->m_flags & eDVBService::dxNoSDT)
970                                 continue;
971                         if (!(dvb_service->m_flags & eDVBService::dxHoldName))
972                         {
973                                 dvb_service->m_service_name = service->second->m_service_name;
974                                 dvb_service->m_service_name_sort = service->second->m_service_name_sort;
975                         }
976                         dvb_service->m_provider_name = service->second->m_provider_name;
977                         if (service->second->m_ca.size())
978                                 dvb_service->m_ca = service->second->m_ca;
979                         if (!dontRemoveOldFlags) // do not remove new found flags when not wished
980                                 dvb_service->m_flags &= ~eDVBService::dxNewFound;
981                 }
982                 else
983                 {
984                         db->addService(service->first, service->second);
985                         if (!(m_flags & scanRemoveServices))
986                                 service->second->m_flags |= eDVBService::dxNewFound;
987                 }
988         }
989 }
990
991 RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionSection &sdt)
992 {
993         const ServiceDescriptionList &services = *sdt.getDescriptions();
994         SCAN_eDebug("ONID: %04x", sdt.getOriginalNetworkId());
995         eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId());
996         
997         /* save correct CHID for this channel */
998         m_chid_current = chid;
999
1000         for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s)
1001         {
1002                 unsigned short service_id = (*s)->getServiceId();
1003                 SCAN_eDebugNoNewLine("SID %04x: ", service_id);
1004                 bool add = true;
1005
1006                 if (m_flags & scanOnlyFree)
1007                 {
1008                         std::map<unsigned short, service>::iterator it =
1009                                 m_pmts_to_read.find(service_id);
1010                         if (it != m_pmts_to_read.end())
1011                         {
1012                                 if (it->second.scrambled)
1013                                 {
1014                                         SCAN_eDebug("is scrambled!");
1015                                         add = false;
1016                                 }
1017                                 else
1018                                         SCAN_eDebug("is free");
1019                         }
1020                         else {
1021                                 SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
1022                                 add = false;
1023                         }
1024                 }
1025
1026                 if (add)
1027                 {
1028                         eServiceReferenceDVB ref;
1029                         ePtr<eDVBService> service = new eDVBService;
1030
1031                         ref.set(chid);
1032                         ref.setServiceID(service_id);
1033
1034                         for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin();
1035                                         desc != (*s)->getDescriptors()->end(); ++desc)
1036                         {
1037                                 switch ((*desc)->getTag())
1038                                 {
1039                                 case SERVICE_DESCRIPTOR:
1040                                 {
1041                                         ServiceDescriptor &d = (ServiceDescriptor&)**desc;
1042                                         ref.setServiceType(d.getServiceType());
1043                                         service->m_service_name = convertDVBUTF8(d.getServiceName());
1044                                         service->genSortName();
1045
1046                                         service->m_provider_name = convertDVBUTF8(d.getServiceProviderName());
1047                                         SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
1048                                         break;
1049                                 }
1050                                 case CA_IDENTIFIER_DESCRIPTOR:
1051                                 {
1052                                         CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
1053                                         const CaSystemIdList &caids = *d.getCaSystemIds();
1054                                         SCAN_eDebugNoNewLine("CA ");
1055                                         for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
1056                                         {
1057                                                 SCAN_eDebugNoNewLine("%04x ", *i);
1058                                                 service->m_ca.push_front(*i);
1059                                         }
1060                                         SCAN_eDebug("");
1061                                         break;
1062                                 }
1063                                 default:
1064                                         SCAN_eDebug("descr<%x>", (*desc)->getTag());
1065                                         break;
1066                                 }
1067                         }
1068
1069                         std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
1070                                 m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
1071
1072                         if (i.second)
1073                         {
1074                                 m_last_service = i.first;
1075                                 m_event(evtNewService);
1076                         }
1077                 }
1078                 if (m_pmt_running && m_pmt_in_progress->first == service_id)
1079                         m_abort_current_pmt = true;
1080                 else
1081                         m_pmts_to_read.erase(service_id);
1082         }
1083
1084         return 0;
1085 }
1086
1087 RESULT eDVBScan::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1088 {
1089         connection = new eConnection(this, m_event.connect(event));
1090         return 0;
1091 }
1092
1093 void eDVBScan::getStats(int &transponders_done, int &transponders_total, int &services)
1094 {
1095         transponders_done = m_ch_scanned.size() + m_ch_unavailable.size();
1096         transponders_total = m_ch_toScan.size() + transponders_done;
1097         services = m_new_services.size();
1098 }
1099
1100 void eDVBScan::getLastServiceName(std::string &last_service_name)
1101 {
1102         if (m_last_service == m_new_services.end())
1103                 last_service_name = "";
1104         else
1105                 last_service_name = m_last_service->second->m_service_name;
1106 }
1107
1108 RESULT eDVBScan::getFrontend(ePtr<iDVBFrontend> &fe)
1109 {
1110         if (m_channel)
1111                 return m_channel->getFrontend(fe);
1112         fe = 0;
1113         return -1;
1114 }
1115
1116 RESULT eDVBScan::getCurrentTransponder(ePtr<iDVBFrontendParameters> &tp)
1117 {
1118         if (m_ch_current)
1119         {
1120                 tp = m_ch_current;
1121                 return 0;
1122         }
1123         tp = 0;
1124         return -1;
1125 }