MythTV  0.28pre
eithelper.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 // Std C headers
4 #include <time.h>
5 
6 // Std C++ headers
7 #include <algorithm>
8 using namespace std;
9 
10 // MythTV includes
11 #include "eithelper.h"
12 #include "eitfixup.h"
13 #include "eitcache.h"
14 #include "mythdb.h"
15 #include "atsctables.h"
16 #include "dvbtables.h"
17 #include "premieretables.h"
18 #include "dishdescriptors.h"
19 #include "premieredescriptors.h"
20 #include "channelutil.h" // for ChannelUtil
21 #include "mythdate.h"
22 #include "programdata.h"
23 #include "programinfo.h" // for subtitle types and audio and video properties
24 #include "scheduledrecording.h" // for ScheduledRecording
25 #include "compat.h" // for gmtime_r on windows.
26 
27 const uint EITHelper::kChunkSize = 20;
29 
30 static uint get_chan_id_from_db_atsc(uint sourceid,
31  uint atscmajor, uint atscminor);
32 static uint get_chan_id_from_db_dvb(uint sourceid, uint serviceid,
33  uint networkid, uint transportid);
34 static uint get_chan_id_from_db_dtv(uint sourceid,
35  uint programnumber, uint tunedchanid);
36 static void init_fixup(FixupMap &fix);
37 
38 #define LOC QString("EITHelper: ")
39 
41  eitfixup(new EITFixUp()),
42  gps_offset(-1 * GPS_LEAP_SECONDS),
43  sourceid(0), channelid(0),
44  maxStarttime(QDateTime()), seenEITother(false)
45 {
47 }
48 
50 {
51  QMutexLocker locker(&eitList_lock);
52  while (db_events.size())
53  delete db_events.dequeue();
54 
55  delete eitfixup;
56 }
57 
59 {
60  QMutexLocker locker(&eitList_lock);
61  return db_events.size();
62 }
63 
70 {
71  QMutexLocker locker(&eitList_lock);
72  uint insertCount = 0;
73 
74  if (db_events.empty())
75  return 0;
76 
78  for (uint i = 0; (i < kChunkSize) && (db_events.size() > 0); i++)
79  {
80  DBEventEIT *event = db_events.dequeue();
81  eitList_lock.unlock();
82 
83  eitfixup->Fix(*event);
84 
85  insertCount += event->UpdateDB(query, 1000);
86  maxStarttime = max (maxStarttime, event->starttime);
87 
88  delete event;
89  eitList_lock.lock();
90  }
91 
92  if (!insertCount)
93  return 0;
94 
95  if (incomplete_events.size() || unmatched_etts.size())
96  {
97  LOG(VB_EIT, LOG_INFO,
98  LOC + QString("Added %1 events -- complete(%2) "
99  "incomplete(%3) unmatched(%4)")
100  .arg(insertCount).arg(db_events.size())
101  .arg(incomplete_events.size()).arg(unmatched_etts.size()));
102  }
103  else
104  {
105  LOG(VB_EIT, LOG_INFO,
106  LOC + QString("Added %1 events").arg(insertCount));
107  }
108 
109  return insertCount;
110 }
111 
112 void EITHelper::SetFixup(uint atsc_major, uint atsc_minor, FixupValue eitfixup)
113 {
114  QMutexLocker locker(&eitList_lock);
115  FixupKey atsc_key = (atsc_major << 16) | atsc_minor;
116  fixup[atsc_key] = eitfixup;
117 }
118 
119 void EITHelper::SetLanguagePreferences(const QStringList &langPref)
120 {
121  QMutexLocker locker(&eitList_lock);
122 
123  uint priority = 1;
124  QStringList::const_iterator it;
125  for (it = langPref.begin(); it != langPref.end(); ++it)
126  {
127  if (!(*it).isEmpty())
128  {
129  uint language_key = iso639_str3_to_key(*it);
130  uint canonoical_key = iso639_key_to_canonical_key(language_key);
131  languagePreferences[canonoical_key] = priority++;
132  }
133  }
134 }
135 
137 {
138  QMutexLocker locker(&eitList_lock);
139  sourceid = _sourceid;
140 }
141 
143 {
144  QMutexLocker locker(&eitList_lock);
145  channelid = _channelid;
146 }
147 
148 void EITHelper::AddEIT(uint atsc_major, uint atsc_minor,
149  const EventInformationTable *eit)
150 {
151  uint atsc_key = (atsc_major << 16) | atsc_minor;
152  EventIDToATSCEvent &events = incomplete_events[atsc_key];
153  EventIDToETT &etts = unmatched_etts[atsc_key];
154 
155  for (uint i = 0; i < eit->EventCount(); i++)
156  {
157  ATSCEvent ev(eit->StartTimeRaw(i), eit->LengthInSeconds(i),
158  eit->ETMLocation(i),
160  eit->Descriptors(i), eit->DescriptorsLength(i));
161 
162  // Look to see if there has been a recent ett message with the same event id.
163  EventIDToETT::iterator it = etts.find(eit->EventID(i));
164  QString ett_text = QString::null;
165  bool found_matching_ett = false;
166  if (it != etts.end())
167  {
168  // Don't use an ett description if it was scanned long in the past.
169  if (!it->IsStale()) {
170  ett_text = it->ett_text;
171  found_matching_ett = true;
172  }
173  etts.erase(it);
174  }
175 
176  // Create an event immediately if a matching ett description was found,
177  // or if item is false, indicating that no ett description should be
178  // expected.
179  if (found_matching_ett || !ev.etm)
180  {
181  CompleteEvent(atsc_major, atsc_minor, ev, ett_text);
182  }
183  else
184  {
185  unsigned char *tmp = new unsigned char[ev.desc_length];
186  memcpy(tmp, eit->Descriptors(i), ev.desc_length);
187  ev.desc = tmp;
188  events.insert(eit->EventID(i), ev);
189  }
190  }
191 }
192 
193 void EITHelper::AddETT(uint atsc_major, uint atsc_minor,
194  const ExtendedTextTable *ett)
195 {
196  uint atsc_key = (atsc_major << 16) | atsc_minor;
197  // Try to match up the ett with an eit event.
198  ATSCSRCToEvents::iterator eits_it = incomplete_events.find(atsc_key);
199  if (eits_it != incomplete_events.end())
200  {
201  EventIDToATSCEvent::iterator it = (*eits_it).find(ett->EventID());
202  if (it != (*eits_it).end())
203  {
204  bool completed_event = false;
205  // Only consider eit events from the recent past.
206  if (!it->IsStale()) {
207  completed_event = true;
209  atsc_major, atsc_minor, *it,
211  }
212 
213  if ((*it).desc)
214  delete [] (*it).desc;
215 
216  (*eits_it).erase(it);
217 
218  if (completed_event) return;
219  }
220  }
221 
222  // Report if an unmatched ett was previously noted and overwrite it.
223  // See also https://code.mythtv.org/trac/ticket/11739
224  EventIDToETT &elist = unmatched_etts[atsc_key];
225  EventIDToETT::iterator existing_unmatched_ett_it =
226  elist.find(ett->EventID());
227  const QString next_ett_text = ett->ExtendedTextMessage()
229  if (existing_unmatched_ett_it != elist.end() &&
230  existing_unmatched_ett_it->ett_text != next_ett_text)
231  {
232  LOG(VB_EIT, LOG_DEBUG, LOC +
233  QString("Overwriting previously unmatched ett. stale: %1 major: %2 "
234  "minor: %3 old ett: %4 new ett: %5")
235  .arg(existing_unmatched_ett_it->IsStale())
236  .arg(atsc_major)
237  .arg(atsc_minor)
238  .arg(existing_unmatched_ett_it->ett_text)
239  .arg(next_ett_text));
240  }
241  elist.insert(ett->EventID(), ATSCEtt(next_ett_text));
242 }
243 
245  QMap<uint,uint> languagePreferences,
246  QString &title, QString &subtitle,
247  QString &description, QMap<QString,QString> &items)
248 {
249  const unsigned char *bestShortEvent =
251  list, DescriptorID::short_event, languagePreferences);
252 
253  // from EN 300 468, Appendix A.2 - Selection of character table
254  unsigned char enc_1[3] = { 0x10, 0x00, 0x01 };
255  unsigned char enc_2[3] = { 0x10, 0x00, 0x02 };
256  unsigned char enc_7[3] = { 0x10, 0x00, 0x07 }; // Latin/Greek Alphabet
257  unsigned char enc_9[3] = { 0x10, 0x00, 0x09 }; // could use { 0x05 } instead
258  unsigned char enc_15[3] = { 0x10, 0x00, 0x0f }; // could use { 0x0B } instead
259  int enc_len = 0;
260  const unsigned char *enc = NULL;
261 
262  // Is this BellExpressVU EIT (Canada) ?
263  // Use an encoding override of ISO 8859-1 (Latin1)
265  {
266  enc = enc_1;
267  enc_len = sizeof(enc_1);
268  }
269 
270  // Is this broken DVB provider in Central Europe?
271  // Use an encoding override of ISO 8859-2 (Latin2)
273  {
274  enc = enc_2;
275  enc_len = sizeof(enc_2);
276  }
277 
278  // Is this broken DVB provider in Western Europe?
279  // Use an encoding override of ISO 8859-9 (Latin5)
281  {
282  enc = enc_9;
283  enc_len = sizeof(enc_9);
284  }
285 
286  // Is this broken DVB provider in Western Europe?
287  // Use an encoding override of ISO 8859-15 (Latin9)
289  {
290  enc = enc_15;
291  enc_len = sizeof(enc_15);
292  }
293 
294  // Is this broken DVB provider in Greece?
295  // Use an encoding override of ISO 8859-7 (Latin/Greek)
297  {
298  enc = enc_7;
299  enc_len = sizeof(enc_7);
300  }
301 
302  if (bestShortEvent)
303  {
304  ShortEventDescriptor sed(bestShortEvent);
305  if (enc)
306  {
307  title = sed.EventName(enc, enc_len);
308  subtitle = sed.Text(enc, enc_len);
309  }
310  else
311  {
312  title = sed.EventName();
313  subtitle = sed.Text();
314  }
315  }
316 
317  vector<const unsigned char*> bestExtendedEvents =
319  list, DescriptorID::extended_event, languagePreferences);
320 
321  description = "";
322  for (uint j = 0; j < bestExtendedEvents.size(); j++)
323  {
324  if (!bestExtendedEvents[j])
325  {
326  description = "";
327  break;
328  }
329 
330  ExtendedEventDescriptor eed(bestExtendedEvents[j]);
331  if (enc)
332  description += eed.Text(enc, enc_len);
333  else
334  description += eed.Text();
335 
336  // add items from the decscriptor to the items
337  items.unite (eed.Items());
338  }
339 }
340 
342  unsigned char &subtitle_type,
343  unsigned char &audio_properties,
344  unsigned char &video_properties)
345 {
346  desc_list_t components =
348  for (uint j = 0; j < components.size(); j++)
349  {
350  ComponentDescriptor component(components[j]);
351  video_properties |= component.VideoProperties();
352  audio_properties |= component.AudioProperties();
353  subtitle_type |= component.SubtitleType();
354  }
355 }
356 
358 {
359  uint chanid = 0;
360  if ((eit->TableID() == TableID::PF_EIT) ||
361  ((eit->TableID() >= TableID::SC_EITbeg) && (eit->TableID() <= TableID::SC_EITend)))
362  {
363  // EITa(ctive)
364  chanid = GetChanID(eit->ServiceID());
365  }
366  else
367  {
368  // EITo(ther)
369  chanid = GetChanID(eit->ServiceID(), eit->OriginalNetworkID(), eit->TSID());
370  // do not reschedule if its only present+following
371  if (eit->TableID() != TableID::PF_EITo)
372  {
373  seenEITother = true;
374  }
375  }
376  if (!chanid)
377  return;
378 
379  uint descCompression = (eit->TableID() > 0x80) ? 2 : 1;
380  FixupValue fix = fixup.value((FixupKey)eit->OriginalNetworkID() << 16);
381  fix |= fixup.value((((FixupKey)eit->TSID()) << 32) |
382  ((FixupKey)eit->OriginalNetworkID() << 16));
383  fix |= fixup.value(((FixupKey)eit->OriginalNetworkID() << 16) |
384  (FixupKey)eit->ServiceID());
385  fix |= fixup.value((((FixupKey)eit->TSID()) << 32) |
386  ((FixupKey)eit->OriginalNetworkID() << 16) |
387  (FixupKey)eit->ServiceID());
389 
390  uint tableid = eit->TableID();
391  uint version = eit->Version();
392  for (uint i = 0; i < eit->EventCount(); i++)
393  {
394  // Skip event if we have already processed it before...
395  if (!eitcache->IsNewEIT(chanid, tableid, version, eit->EventID(i),
396  eit->EndTimeUnixUTC(i)))
397  {
398  continue;
399  }
400 
401  QString title = QString("");
402  QString subtitle = QString("");
403  QString description = QString("");
404  QString category = QString("");
406  unsigned char subtitle_type=0, audio_props=0, video_props=0;
407  uint season = 0, episode = 0, totalepisodes = 0;
408  QMap<QString,QString> items;
409 
410  // Parse descriptors
412  eit->Descriptors(i), eit->DescriptorsLength(i));
413 
414  const unsigned char *dish_event_name = NULL;
415  if (EITFixUp::kFixDish & fix)
416  {
417  dish_event_name = MPEGDescriptor::Find(
419  }
420 
421  if (dish_event_name)
422  {
423  DishEventNameDescriptor dend(dish_event_name);
424  if (dend.HasName())
425  title = dend.Name(descCompression);
426 
427  const unsigned char *dish_event_description =
430  if (dish_event_description)
431  {
432  DishEventDescriptionDescriptor dedd(dish_event_description);
433  if (dedd.HasDescription())
434  description = dedd.Description(descCompression);
435  }
436  }
437  else
438  {
440  title, subtitle, description, items);
441  }
442 
443  parse_dvb_component_descriptors(list, subtitle_type, audio_props,
444  video_props);
445 
446  QString programId = QString("");
447  QString seriesId = QString("");
448  QString rating = QString("");
449  QString rating_system = QString("");
450  QString advisory = QString("");
451  float stars = 0.0;
452  QDate originalairdate;
453 
454  if (EITFixUp::kFixDish & fix)
455  {
456  const unsigned char *mpaa_data = MPEGDescriptor::Find(
458  if (mpaa_data)
459  {
460  DishEventMPAADescriptor mpaa(mpaa_data);
461  stars = mpaa.stars();
462 
463  if (stars) // Only movies for now
464  {
465  rating = mpaa.rating();
466  rating_system = "MPAA";
467  advisory = mpaa.advisory();
468  }
469  }
470 
471  if (!stars) // Not MPAA rated, check VCHIP
472  {
473  const unsigned char *vchip_data = MPEGDescriptor::Find(
475  if (vchip_data)
476  {
477  DishEventVCHIPDescriptor vchip(vchip_data);
478  rating = vchip.rating();
479  rating_system = "VCHIP";
480  advisory = vchip.advisory();
481  }
482  }
483 
484  if (!advisory.isEmpty() && !rating.isEmpty())
485  rating += ", " + advisory;
486  else if (!advisory.isEmpty())
487  {
488  rating = advisory;
489  rating_system = "advisory";
490  }
491 
492  const unsigned char *tags_data = MPEGDescriptor::Find(
494  if (tags_data)
495  {
496  DishEventTagsDescriptor tags(tags_data);
497  seriesId = tags.seriesid();
498  programId = tags.programid();
499  originalairdate = tags.originalairdate(); // future use
500 
501  if (programId.startsWith("MV") || programId.startsWith("SP"))
502  seriesId = "";
503  }
504 
505  const unsigned char *properties_data = MPEGDescriptor::Find(
507  if (properties_data)
508  {
509  DishEventPropertiesDescriptor properties(properties_data);
510  subtitle_type |= properties.SubtitleProperties(descCompression);
511  audio_props |= properties.AudioProperties(descCompression);
512  }
513  }
514 
515  const unsigned char *content_data =
517  if (content_data)
518  {
519  if ((EITFixUp::kFixDish & fix) || (EITFixUp::kFixBell & fix))
520  {
521  DishContentDescriptor content(content_data);
522  switch (content.GetTheme())
523  {
524  case kThemeMovie :
525  category_type = ProgramInfo::kCategoryMovie;
526  break;
527  case kThemeSeries :
528  category_type = ProgramInfo::kCategorySeries;
529  break;
530  case kThemeSports :
531  category_type = ProgramInfo::kCategorySports;
532  break;
533  default :
534  category_type = ProgramInfo::kCategoryNone;
535  }
536  if (EITFixUp::kFixDish & fix)
537  category = content.GetCategory();
538  }
539  else if (EITFixUp::kFixAUDescription & fix)//AU Freeview assigned genres
540  {
541  ContentDescriptor content(content_data);
542  switch (content.Nibble1(0))
543  {
544  case 0x01:
545  category = "Movie";
546  break;
547  case 0x02:
548  category = "News";
549  break;
550  case 0x03:
551  category = "Entertainment";
552  break;
553  case 0x04:
554  category = "Sport";
555  break;
556  case 0x05:
557  category = "Children";
558  break;
559  case 0x06:
560  category = "Music";
561  break;
562  case 0x07:
563  category = "Arts/Culture";
564  break;
565  case 0x08:
566  category = "Current Affairs";
567  break;
568  case 0x09:
569  category = "Education";
570  break;
571  case 0x0A:
572  category = "Infotainment";
573  break;
574  case 0x0B:
575  category = "Special";
576  break;
577  case 0x0C:
578  category = "Comedy";
579  break;
580  case 0x0D:
581  category = "Drama";
582  break;
583  case 0x0E:
584  category = "Documentary";
585  break;
586  default:
587  category = "";
588  break;
589  }
590  category_type = content.GetMythCategory(0);
591  }
592  else if (EITFixUp::kFixGreekEIT & fix)//Greek
593  {
594  ContentDescriptor content(content_data);
595  switch (content.Nibble2(0))
596  {
597  case 0x01:
598  category = "Ταινία"; // confirmed
599  break;
600  case 0x02:
601  category = "Ενημερωτικό"; // confirmed
602  break;
603  case 0x04:
604  category = "Αθλητικό"; // confirmed
605  break;
606  case 0x05:
607  category = "Παιδικό"; // confirmed
608  break;
609  case 0x09:
610  category = "Ντοκιμαντέρ"; // confirmed
611  break;
612  default:
613  category = "";
614  break;
615  }
616  category_type = content.GetMythCategory(2);
617  }
618  else
619  {
620  ContentDescriptor content(content_data);
621  category = content.GetDescription(0);
622 #if 0 /* there is no category_type in DVB EIT */
623  category_type = content.GetMythCategory(0);
624 #endif
625  }
626  }
627 
628  desc_list_t contentIds =
630  for (uint j = 0; j < contentIds.size(); j++)
631  {
632  DVBContentIdentifierDescriptor desc(contentIds[j]);
633  for (uint k = 0; k < desc.CRIDCount(); k++)
634  {
635  if (desc.ContentEncoding(k) == 0)
636  {
637  // The CRID is a URI. It could contain UTF8 sequences encoded
638  // as %XX but there's no advantage in decoding them.
639  // The BBC currently uses private types 0x31 and 0x32.
640  // IDs from the authority eventis.nl are not fit for our scheduler
641  if (desc.ContentType(k) == 0x01 || desc.ContentType(k) == 0x31)
642  {
643  if (!desc.ContentId(k).startsWith ("eventis.nl/"))
644  {
645  programId = desc.ContentId(k);
646  }
647  }
648  else if (desc.ContentType(k) == 0x02 || desc.ContentType(k) == 0x32)
649  {
650  if (!desc.ContentId(k).startsWith ("eventis.nl/"))
651  {
652  seriesId = desc.ContentId(k);
653  }
654  category_type = ProgramInfo::kCategorySeries;
655  }
656  }
657  }
658  }
659 
660  /* if we don't have a subtitle, try to parse one from private descriptors */
661  if (subtitle.isEmpty()) {
662  bool isUPC = false;
663  /* is this event carrying UPC private data? */
665  for (uint j = 0; j < private_data_specifiers.size(); j++) {
666  PrivateDataSpecifierDescriptor desc(private_data_specifiers[j]);
668  isUPC = true;
669  }
670  }
671 
672  if (isUPC) {
674  for (uint j = 0; j < subtitles.size(); j++) {
675  PrivateUPCCablecomEpisodeTitleDescriptor desc(subtitles[j]);
676 
677  subtitle = desc.Text();
678  }
679  }
680  }
681 
682 
683  QDateTime starttime = eit->StartTimeUTC(i);
684  // fix starttime only if the duration is a multiple of a minute
685  if (!(eit->DurationInSeconds(i) % 60))
686  EITFixUp::TimeFix(starttime);
687  QDateTime endtime = starttime.addSecs(eit->DurationInSeconds(i));
688 
689  DBEventEIT *event = new DBEventEIT(
690  chanid,
691  title, subtitle, description,
692  category, category_type,
693  starttime, endtime, fix,
694  subtitle_type,
695  audio_props,
696  video_props, stars,
697  seriesId, programId,
698  season, episode, totalepisodes);
699  event->items = items;
700 
701  db_events.enqueue(event);
702  }
703 }
704 
705 // This function gets special EIT data from the German provider Premiere
706 // for the option channels Premiere Sport and Premiere Direkt
708 {
709  // set fixup for Premiere
710  FixupValue fix = fixup.value(133 << 16);
712 
713  QString title = QString("");
714  QString subtitle = QString("");
715  QString description = QString("");
716  QString category = QString("");
718  unsigned char subtitle_type=0, audio_props=0, video_props=0;
719  uint season = 0, episode = 0, totalepisodes = 0;
720  QMap<QString,QString> items;
721 
722  // Parse descriptors
724  cit->Descriptors(), cit->DescriptorsLength());
725 
727  title, subtitle, description, items);
728 
729  parse_dvb_component_descriptors(list, subtitle_type, audio_props,
730  video_props);
731 
732  const unsigned char *content_data =
734  if (content_data)
735  {
736  ContentDescriptor content(content_data);
737  // fix events without real content data
738  if (content.Nibble(0)==0x00)
739  {
740  if(content.UserNibble(0)==0x1)
741  {
742  category_type = ProgramInfo::kCategoryMovie;
743  }
744  else if(content.UserNibble(0)==0x0)
745  {
746  category_type = ProgramInfo::kCategorySports;
747  category = QObject::tr("Sports");
748  }
749  }
750  else
751  {
752  category_type = content.GetMythCategory(0);
753  category = content.GetDescription(0);
754  }
755  }
756 
757  uint tableid = cit->TableID();
758  uint version = cit->Version();
759  uint contentid = cit->ContentID();
760  // fake endtime
761  uint endtime = MythDate::current().addDays(1).toTime_t();
762 
763  // Find Transmissions
764  desc_list_t transmissions =
767  for(uint j=0; j< transmissions.size(); j++)
768  {
769  PremiereContentTransmissionDescriptor transmission(transmissions[j]);
770  uint networkid = transmission.OriginalNetworkID();
771  uint tsid = transmission.TSID();
772  uint serviceid = transmission.ServiceID();
773 
774  uint chanid = GetChanID(serviceid, networkid, tsid);
775 
776  if (!chanid)
777  {
778  LOG(VB_EIT, LOG_INFO, LOC +
779  QString("Premiere EIT for NIT %1, TID %2, SID %3, "
780  "count %4, title: %5. Channel not found!")
781  .arg(networkid).arg(tsid).arg(serviceid)
782  .arg(transmission.TransmissionCount()).arg(title));
783  continue;
784  }
785 
786  // Skip event if we have already processed it before...
787  if (!eitcache->IsNewEIT(chanid, tableid, version, contentid, endtime))
788  {
789  continue;
790  }
791 
792  for (uint k=0; k<transmission.TransmissionCount(); ++k)
793  {
794  QDateTime starttime = transmission.StartTimeUTC(k);
795  // fix starttime only if the duration is a multiple of a minute
796  if (!(cit->DurationInSeconds() % 60))
797  EITFixUp::TimeFix(starttime);
798  QDateTime endtime = starttime.addSecs(cit->DurationInSeconds());
799 
800  DBEventEIT *event = new DBEventEIT(
801  chanid,
802  title, subtitle, description,
803  category, category_type,
804  starttime, endtime, fix,
805  subtitle_type,
806  audio_props,
807  video_props, 0.0,
808  "", "",
809  season, episode, totalepisodes);
810  event->items = items;
811 
812  db_events.enqueue(event);
813  }
814  }
815 }
816 
817 
819 {
820  eitcache->PruneOldEntries(timestamp);
821 }
822 
824 {
825  eitcache->WriteToDB();
826 }
827 
829 // private methods and functions below this line //
831 
832 void EITHelper::CompleteEvent(uint atsc_major, uint atsc_minor,
833  const ATSCEvent &event,
834  const QString &ett)
835 {
836  uint chanid = GetChanID(atsc_major, atsc_minor);
837  if (!chanid)
838  return;
839 
840  QDateTime starttime = MythDate::fromTime_t(
841  event.start_time + GPS_EPOCH + gps_offset);
842 
843  // fix starttime only if the duration is a multiple of a minute
844  if (!(event.length % 60))
845  EITFixUp::TimeFix(starttime);
846  QDateTime endtime = starttime.addSecs(event.length);
847 
848  desc_list_t list = MPEGDescriptor::Parse(event.desc, event.desc_length);
849  unsigned char subtitle_type =
852  unsigned char audio_properties = AUD_UNKNOWN;
853  unsigned char video_properties = VID_UNKNOWN;
854 
855  uint atsc_key = (atsc_major << 16) | atsc_minor;
856 
857  QMutexLocker locker(&eitList_lock);
858  QString title = event.title;
859  QString subtitle = ett;
860  db_events.enqueue(new DBEventEIT(chanid, title, subtitle,
861  starttime, endtime,
862  fixup.value(atsc_key), subtitle_type,
863  audio_properties, video_properties));
864 }
865 
866 uint EITHelper::GetChanID(uint atsc_major, uint atsc_minor)
867 {
868  uint64_t key;
869  key = ((uint64_t) sourceid);
870  key |= ((uint64_t) atsc_minor) << 16;
871  key |= ((uint64_t) atsc_major) << 32;
872 
873  ServiceToChanID::const_iterator it = srv_to_chanid.find(key);
874  if (it != srv_to_chanid.end())
875  return max(*it, 0u);
876 
877  uint chanid = get_chan_id_from_db_atsc(sourceid, atsc_major, atsc_minor);
878  srv_to_chanid[key] = chanid;
879 
880  return chanid;
881 }
882 
883 uint EITHelper::GetChanID(uint serviceid, uint networkid, uint tsid)
884 {
885  uint64_t key;
886  key = ((uint64_t) sourceid);
887  key |= ((uint64_t) serviceid) << 16;
888  key |= ((uint64_t) networkid) << 32;
889  key |= ((uint64_t) tsid) << 48;
890 
891  ServiceToChanID::const_iterator it = srv_to_chanid.find(key);
892  if (it != srv_to_chanid.end())
893  return max(*it, 0u);
894 
895  uint chanid = get_chan_id_from_db_dvb(sourceid, serviceid, networkid, tsid);
896  srv_to_chanid[key] = chanid;
897 
898  return chanid;
899 }
900 
902 {
903  uint64_t key;
904  key = ((uint64_t) sourceid);
905  key |= ((uint64_t) program_number) << 16;
906  key |= ((uint64_t) channelid) << 32;
907 
908  ServiceToChanID::const_iterator it = srv_to_chanid.find(key);
909  if (it != srv_to_chanid.end())
910  return max(*it, 0u);
911 
912  uint chanid = get_chan_id_from_db_dtv(sourceid, program_number, channelid);
913  srv_to_chanid[key] = chanid;
914 
915  return chanid;
916 }
917 
919  uint atsc_major, uint atsc_minor)
920 {
921  MSqlQuery query(MSqlQuery::InitCon());
922  query.prepare(
923  "SELECT chanid, useonairguide "
924  "FROM channel "
925  "WHERE atsc_major_chan = :MAJORCHAN AND "
926  " atsc_minor_chan = :MINORCHAN AND "
927  " sourceid = :SOURCEID");
928  query.bindValue(":MAJORCHAN", atsc_major);
929  query.bindValue(":MINORCHAN", atsc_minor);
930  query.bindValue(":SOURCEID", sourceid);
931 
932  if (!query.exec() || !query.isActive())
933  MythDB::DBError("Looking up chanid 1", query);
934  else if (query.next())
935  {
936  bool useOnAirGuide = query.value(1).toBool();
937  return (useOnAirGuide) ? query.value(0).toUInt() : 0;
938  }
939 
940  return 0;
941 }
942 
943 // Figure out the chanid for this channel
944 static uint get_chan_id_from_db_dvb(uint sourceid, uint serviceid,
945  uint networkid, uint transportid)
946 {
947  uint chanid = 0;
948  bool useOnAirGuide = false;
949  MSqlQuery query(MSqlQuery::InitCon());
950 
951  // DVB Link to chanid
952  QString qstr =
953  "SELECT chanid, useonairguide, channel.sourceid "
954  "FROM channel, dtv_multiplex "
955  "WHERE serviceid = :SERVICEID AND "
956  " networkid = :NETWORKID AND "
957  " transportid = :TRANSPORTID AND "
958  " channel.mplexid = dtv_multiplex.mplexid";
959 
960  query.prepare(qstr);
961  query.bindValue(":SERVICEID", serviceid);
962  query.bindValue(":NETWORKID", networkid);
963  query.bindValue(":TRANSPORTID", transportid);
964 
965  if (!query.exec() || !query.isActive())
966  MythDB::DBError("Looking up chanID", query);
967 
968  if (query.size() == 0) {
969  // Attempt fuzzy matching, by skipping the tsid
970  // DVB Link to chanid
971  QString qstr =
972  "SELECT chanid, useonairguide, channel.sourceid "
973  "FROM channel, dtv_multiplex "
974  "WHERE serviceid = :SERVICEID AND "
975  " networkid = :NETWORKID AND "
976  " channel.mplexid = dtv_multiplex.mplexid";
977 
978  query.prepare(qstr);
979  query.bindValue(":SERVICEID", serviceid);
980  query.bindValue(":NETWORKID", networkid);
981  if (!query.exec() || !query.isActive())
982  MythDB::DBError("Looking up chanID in fuzzy mode", query);
983  }
984 
985  while (query.next())
986  {
987  // Check to see if we are interested in this channel
988  chanid = query.value(0).toUInt();
989  useOnAirGuide = query.value(1).toBool();
990  if (sourceid == query.value(2).toUInt())
991  return useOnAirGuide ? chanid : 0;
992  }
993 
994  if (query.size() > 1)
995  {
996  LOG(VB_EIT, LOG_INFO,
997  LOC + QString("found %1 channels for networdid %2, "
998  "transportid %3, serviceid %4 but none "
999  "for current sourceid %5.")
1000  .arg(query.size()).arg(networkid).arg(transportid)
1001  .arg(serviceid).arg(sourceid));
1002  }
1003 
1004  return useOnAirGuide ? chanid : 0;
1005 }
1006 
1007 /* Figure out the chanid for this channel from the sourceid,
1008  * program_number/service_id and the chanid of the channel we are tuned to
1009  *
1010  * TODO for SPTS (e.g. HLS / IPTV) it would be useful to match without an entry
1011  * in dtv_multiplex
1012  */
1013 static uint get_chan_id_from_db_dtv(uint sourceid, uint serviceid,
1014  uint tunedchanid)
1015 {
1016  uint chanid = 0;
1017  bool useOnAirGuide = false;
1018  MSqlQuery query(MSqlQuery::InitCon());
1019 
1020  // DVB Link to chanid
1021  QString qstr =
1022  "SELECT c1.chanid, c1.useonairguide, c1.sourceid "
1023  "FROM channel c1, dtv_multiplex m, channel c2 "
1024  "WHERE c1.serviceid = :SERVICEID AND "
1025  " c1.mplexid = m.mplexid AND "
1026  " m.mplexid = c2.mplexid AND "
1027  " c2.chanid = :CHANID";
1028 
1029  query.prepare(qstr);
1030  query.bindValue(":SERVICEID", serviceid);
1031  query.bindValue(":CHANID", tunedchanid);
1032 
1033  if (!query.exec() || !query.isActive())
1034  MythDB::DBError("Looking up chanID", query);
1035 
1036  while (query.next())
1037  {
1038  // Check to see if we are interested in this channel
1039  chanid = query.value(0).toUInt();
1040  useOnAirGuide = query.value(1).toBool();
1041  if (sourceid == query.value(2).toUInt())
1042  return useOnAirGuide ? chanid : 0;
1043  }
1044 
1045  if (query.size() > 1)
1046  {
1047  LOG(VB_EIT, LOG_INFO,
1048  LOC + QString("found %1 channels for multiplex of chanid %2, "
1049  "serviceid %3 but none "
1050  "for current sourceid %4.")
1051  .arg(query.size()).arg(tunedchanid)
1052  .arg(serviceid).arg(sourceid));
1053  }
1054 
1055  return useOnAirGuide ? chanid : 0;
1056 }
1057 
1058 static void init_fixup(FixupMap &fix)
1059 {
1061  // Fixups to make EIT provided listings more useful
1062  // transport_id<<32 | netword_id<<16 | service_id
1063 
1064  // Bell Express VU Canada
1065  fix[ 256U << 16] = EITFixUp::kFixBell;
1066  fix[ 257U << 16] = EITFixUp::kFixBell;
1067  fix[ 4100U << 16] = EITFixUp::kFixBell;
1068  fix[ 4101U << 16] = EITFixUp::kFixBell;
1069  fix[ 4102U << 16] = EITFixUp::kFixBell;
1070  fix[ 4103U << 16] = EITFixUp::kFixBell;
1071  fix[ 4104U << 16] = EITFixUp::kFixBell;
1072  fix[ 4105U << 16] = EITFixUp::kFixBell;
1073  fix[ 4106U << 16] = EITFixUp::kFixBell;
1074  fix[ 4107U << 16] = EITFixUp::kFixBell;
1075  fix[ 4097U << 16] = EITFixUp::kFixBell;
1076  fix[ 4098U << 16] = EITFixUp::kFixBell;
1077 
1078  // United Kingdom - DVB-T/T2
1079  fix[ 9018U << 16] = EITFixUp::kFixUK;
1080 
1081  // UK - Astra 28.2
1082  for (int i = 2001; i <= 2035; ++i)
1083  fix[ (long long)i << 32 | 2U << 16] = EITFixUp::kFixUK;
1084 
1085  fix[ 2036LL << 32 | 2U << 16] = EITFixUp::kFixUK | EITFixUp::kFixHTML;
1086 
1087  for (int i = 2037; i <= 2057; ++i)
1088  fix[ (long long)i << 32 | 2U << 16] = EITFixUp::kFixUK;
1089  fix[ 2061LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1090  fix[ 2063LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1091  fix[ 2064LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1092  fix[ 2066LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1093  fix[ 2068LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1094  fix[ 2069LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1095  fix[ 2076LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1096  fix[ 2081LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1097  fix[ 2096LL << 32 | 2U << 16] = EITFixUp::kFixUK | EITFixUp::kFixHTML;
1098  fix[ 2301LL << 32 | 2U << 16] = EITFixUp::kFixUK | EITFixUp::kFixHTML;
1099  fix[ 2302LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1100  fix[ 2303LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1101  fix[ 2304LL << 32 | 2U << 16] = EITFixUp::kFixUK | EITFixUp::kFixHTML;
1102  fix[ 2305LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1103  fix[ 2306LL << 32 | 2U << 16] = EITFixUp::kFixUK | EITFixUp::kFixHTML;
1104  fix[ 2311LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1105  fix[ 2312LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1106  fix[ 2313LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1107  fix[ 2314LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1108  fix[ 2315LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1109  fix[ 2316LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1110  for (int i = 2401; i <= 2413; ++i)
1111  fix[ (long long)i << 32 | 2U << 16] = EITFixUp::kFixUK;
1112  fix[ 2601LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1113  fix[ 2602LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1114  fix[ 2603LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1115  fix[ 2604LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1116  fix[ 2612LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1117  fix[ 2614LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1118  fix[ 2611LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1119  fix[ 2612LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1120  fix[ 2613LL << 32 | 2U << 16] = EITFixUp::kFixUK;
1121 
1122  // R.caroline
1123  fix[ 2315LL << 32 | 59U << 16] = EITFixUp::kFixUK;
1124 
1125  // ComHem Sweden
1126  fix[40999U << 16 ] = EITFixUp::kFixComHem;
1127  fix[40999U << 16 | 1070] = EITFixUp::kFixSubtitle;
1128  fix[40999U << 16 | 1308] = EITFixUp::kFixSubtitle;
1129  fix[40999U << 16 | 1041] = EITFixUp::kFixSubtitle;
1130  fix[40999U << 16 | 1306] = EITFixUp::kFixSubtitle;
1131  fix[40999U << 16 | 1307] = EITFixUp::kFixSubtitle;
1132  fix[40999U << 16 | 1030] = EITFixUp::kFixSubtitle;
1133  fix[40999U << 16 | 1016] = EITFixUp::kFixSubtitle;
1134  fix[40999U << 16 | 1131] = EITFixUp::kFixSubtitle;
1135  fix[40999U << 16 | 1068] = EITFixUp::kFixSubtitle;
1136  fix[40999U << 16 | 1069] = EITFixUp::kFixSubtitle;
1137 
1138  // Australia
1139  fix[ 4096U << 16] = EITFixUp::kFixAUStar;
1140  fix[ 4096U << 16] = EITFixUp::kFixAUStar;
1141  fix[ 4112U << 16] = EITFixUp::kFixAUDescription | EITFixUp::kFixAUFreeview; // ABC Brisbane
1142  fix[ 4114U << 16] = EITFixUp::kFixAUDescription | EITFixUp::kFixAUFreeview | EITFixUp::kFixAUNine;; // Nine Brisbane
1143  fix[ 4115U << 16] = EITFixUp::kFixAUDescription | EITFixUp::kFixAUSeven; //Seven
1144  fix[ 4116U << 16] = EITFixUp::kFixAUDescription; //Ten
1145  fix[ 12801U << 16] = EITFixUp::kFixAUFreeview | EITFixUp::kFixAUDescription; //ABC
1146  fix[ 12802U << 16] = EITFixUp::kFixAUDescription; //SBS
1148  fix[ 12842U << 16] = EITFixUp::kFixAUDescription; // 31 Brisbane
1149  fix[ 12862U << 16] = EITFixUp::kFixAUDescription; //WestTV
1150 
1151  // MultiChoice Africa
1152  fix[ 6144U << 16] = EITFixUp::kFixMCA;
1153 
1154  // RTL Subtitle parsing
1155  fix[ 1089LL << 32 | 1 << 16] = // DVB-S
1156  fix[ 1041LL << 32 | 1 << 16] = // DVB-S RTL Group HD Austria Transponder
1157  fix[ 1057LL << 32 | 1 << 16] = // DVB-S RTL Group HD Transponder
1158  fix[ 773LL << 32 | 8468U << 16] = // DVB-T Berlin/Brandenburg
1159  fix[ 2819LL << 32 | 8468U << 16] = // DVB-T Niedersachsen + Bremen
1160  fix[ 8706LL << 32 | 8468U << 16] = // DVB-T NRW
1161  fix[ 12801LL << 32 | 8468U << 16] = // DVB-T Bayern
1163 
1164  // Mark HD+ channels as HDTV
1165  fix[ 1041LL << 32 | 1 << 16] = EITFixUp::kFixHDTV;
1166  fix[ 1055LL << 32 | 1 << 16] = EITFixUp::kFixHDTV;
1167  fix[ 1057LL << 32 | 1 << 16] = EITFixUp::kFixHDTV;
1168  fix[ 1109LL << 32 | 1 << 16] = EITFixUp::kFixHDTV;
1169 
1170  // PRO7/SAT.1
1171  fix[ 1017LL << 32 | 1 << 16] = EITFixUp::kFixHDTV | EITFixUp::kFixP7S1;
1172  fix[ 1031LL << 32 | 1 << 16 | 5300] = EITFixUp::kFixHDTV | EITFixUp::kFixP7S1;
1173  fix[ 1031LL << 32 | 1 << 16 | 5301] = EITFixUp::kFixHDTV | EITFixUp::kFixP7S1;
1174  fix[ 1031LL << 32 | 1 << 16 | 5302] = EITFixUp::kFixHDTV | EITFixUp::kFixP7S1;
1175  fix[ 1031LL << 32 | 1 << 16 | 5303] = EITFixUp::kFixHDTV | EITFixUp::kFixP7S1;
1176  fix[ 1031LL << 32 | 1 << 16 | 5310] = EITFixUp::kFixP7S1;
1177  fix[ 1031LL << 32 | 1 << 16 | 5311] = EITFixUp::kFixP7S1;
1178  fix[ 1107LL << 32 | 1 << 16] = EITFixUp::kFixP7S1;
1179  fix[ 1082LL << 32 | 1 << 16] = EITFixUp::kFixP7S1;
1180  fix[ 5LL << 32 | 133 << 16 | 776] = EITFixUp::kFixP7S1;
1181  fix[ 8468 << 16 | 16426] = EITFixUp::kFixP7S1; // ProSieben MAXX - DVB-T Rhein/Main
1182  fix[ 8707LL << 32 | 8468 << 16] = EITFixUp::kFixP7S1; // ProSieben Sat.1 Mux - DVB-T Rhein/Main
1183 
1184  // Premiere EIT processing
1185  fix[ 1LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1186  fix[ 2LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1187  fix[ 3LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1188  fix[ 4LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1189  fix[ 6LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1190  fix[ 8LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1191  fix[ 10LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1192  fix[ 11LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1193  fix[ 12LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1194  fix[ 13LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1195  fix[ 14LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1196  fix[ 15LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1197  fix[ 17LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
1198  // Mark Premiere HD, AXN HD and Discovery HD as HDTV
1199  fix[ 6LL << 32 | 133 << 16 | 129] = EITFixUp::kFixHDTV;
1200  fix[ 6LL << 32 | 133 << 16 | 130] = EITFixUp::kFixHDTV;
1201  fix[ 10LL << 32 | 133 << 16 | 125] = EITFixUp::kFixHDTV;
1202 
1203  // Netherlands DVB-C
1204  fix[ 1000U << 16] = EITFixUp::kFixNL;
1205  // Canal Digitaal DVB-S 19.2 Dutch/Belgian ONID 53 covers all CanalDigitaal TiD
1206  fix[ 53U << 16] = EITFixUp::kFixNL;
1207  // Canal Digitaal DVB-S 23.5 Dutch/Belgian
1208  fix[ 3202LL << 32 | 3U << 16] = EITFixUp::kFixNL;
1209  fix[ 3208LL << 32 | 3U << 16] = EITFixUp::kFixNL;
1210  fix[ 3211LL << 32 | 3U << 16] = EITFixUp::kFixNL;
1211  fix[ 3222LL << 32 | 3U << 16] = EITFixUp::kFixNL;
1212  fix[ 3225LL << 32 | 3U << 16] = EITFixUp::kFixNL;
1213 
1214  // Finland
1215  fix[ 8438U << 16] = // DVB-T Espoo
1216  fix[ 42249U << 16] = // DVB-C Welho
1217  fix[ 15U << 16] = // DVB-C Welho
1219 
1220  // DVB-C YouSee (Denmark)
1221  fix[65024U << 16] = EITFixUp::kFixDK;
1222 
1223  // DVB-S(2) Thor 0.8W Norwegian
1224  fix[70U << 16] = EITFixUp::kFixNO;
1225 
1226  // DVB-T NTV/NRK (Norway)
1227  fix[910LL << 32 | 8770U << 16 | 0x006f] = EITFixUp::kFixNRK_DVBT; //NRK Folkemusikk
1228  fix[910LL << 32 | 8770U << 16 | 0x0070] = EITFixUp::kFixNRK_DVBT; //NRK Stortinget
1229  fix[910LL << 32 | 8770U << 16 | 0x0071] = EITFixUp::kFixNRK_DVBT; //NRK Super
1230  fix[910LL << 32 | 8770U << 16 | 0x0072] = EITFixUp::kFixNRK_DVBT; //NRK Sport
1231  fix[910LL << 32 | 8770U << 16 | 0x0073] = EITFixUp::kFixNRK_DVBT; //NRK Gull
1232  fix[910LL << 32 | 8770U << 16 | 0x0074] = EITFixUp::kFixNRK_DVBT; //NRK Jazz
1233  fix[910LL << 32 | 8770U << 16 | 0x0067] = EITFixUp::kFixNRK_DVBT; //NRK Super / NRK3
1234  fix[910LL << 32 | 8770U << 16 | 0x0068] = EITFixUp::kFixNRK_DVBT; //NRK Tegnspr�
1235  fix[910LL << 32 | 8770U << 16 | 0x0069] = EITFixUp::kFixNRK_DVBT; //NRK P2
1236  fix[910LL << 32 | 8770U << 16 | 0x006a] = EITFixUp::kFixNRK_DVBT; //NRK P3
1237  fix[910LL << 32 | 8770U << 16 | 0x006b] = EITFixUp::kFixNRK_DVBT; //NRK Alltid Nyheter
1238  fix[910LL << 32 | 8770U << 16 | 0x006c] = EITFixUp::kFixNRK_DVBT; //NRK mP3
1239  fix[910LL << 32 | 8770U << 16 | 0x006d] = EITFixUp::kFixNRK_DVBT; //NRK Klassisk
1240  fix[910LL << 32 | 8770U << 16 | 0x006e] = EITFixUp::kFixNRK_DVBT; //NRK S�i Radio
1241  fix[910LL << 32 | 8770U << 16 | 0x0066] = EITFixUp::kFixNRK_DVBT; //NRK2
1242  fix[910LL << 32 | 8770U << 16 | 0x03f0] = EITFixUp::kFixNRK_DVBT; //NRK1 M�e og Romsdal
1243  fix[910LL << 32 | 8770U << 16 | 0x0455] = EITFixUp::kFixNRK_DVBT; //NRK P1 Tr�delag
1244  fix[910LL << 32 | 8770U << 16 | 0x03f1] = EITFixUp::kFixNRK_DVBT; //NRK1 Midtnytt
1245 
1247  // Special Early fixups for providers that break DVB EIT spec.
1248  // transport_id<<32 | network_id<<16 | service_id
1249 
1250  // Bell Express VU Canada
1251  fix[ 256U << 16] |= EITFixUp::kEFixForceISO8859_1;
1252  fix[ 257U << 16] |= EITFixUp::kEFixForceISO8859_1;
1253  fix[4100U << 16] |= EITFixUp::kEFixForceISO8859_1;
1254  fix[4101U << 16] |= EITFixUp::kEFixForceISO8859_1;
1255  fix[4102U << 16] |= EITFixUp::kEFixForceISO8859_1;
1256  fix[4103U << 16] |= EITFixUp::kEFixForceISO8859_1;
1257  fix[4104U << 16] |= EITFixUp::kEFixForceISO8859_1;
1258  fix[4105U << 16] |= EITFixUp::kEFixForceISO8859_1;
1259  fix[4106U << 16] |= EITFixUp::kEFixForceISO8859_1;
1260  fix[4107U << 16] |= EITFixUp::kEFixForceISO8859_1;
1261  fix[4097U << 16] |= EITFixUp::kEFixForceISO8859_1;
1262  fix[4098U << 16] |= EITFixUp::kEFixForceISO8859_1;
1263 
1264  //DVB-T Germany Berlin HSE/MonA TV
1265  fix[ 772LL << 32 | 8468 << 16 | 16387] = EITFixUp::kEFixForceISO8859_15;
1266  //DVB-T Germany Ruhrgebiet Tele 5
1267  //fix[ 8707LL << 32 | 8468 << 16 | 16413] = EITFixUp::kEFixForceISO8859_15; // they are sending the ISO 8859-9 signalling now
1268  // ANIXE
1269  fix[ 8707LL << 32 | 8468U << 16 | 16426 ] = // DVB-T Rhein-Main
1271 
1272  // DVB-C Kabel Deutschland encoding fixes Germany
1273  fix[ 112LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
1274  fix[ 10000LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
1275  fix[ 10001LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
1276  fix[ 10002LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
1277  fix[ 10003LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
1278  fix[ 10006LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
1279  fix[ 10009LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
1280  fix[ 10010LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
1281  // Mark program on the HD transponders as HDTV
1282  fix[ 10012LL << 32 | 61441U << 16] = EITFixUp::kFixHDTV;
1283  fix[ 10013LL << 32 | 61441U << 16] = EITFixUp::kFixHDTV;
1284  // On transport 10004 only DMAX needs no fixing:
1285  fix[10004LL<<32 | 61441U << 16 | 50403] = // BBC World Service
1286  fix[10004LL<<32 | 61441U << 16 | 53101] = // BBC Prime (engl)
1287  fix[10004LL<<32 | 61441U << 16 | 53108] = // Toon Disney (engl)
1288  fix[10004LL<<32 | 61441U << 16 | 53109] = // Sky News (engl)
1289  fix[10004LL<<32 | 61441U << 16 | 53406] = // BBC Prime
1290  fix[10004LL<<32 | 61441U << 16 | 53407] = // Boomerang (engl)
1291  fix[10004LL<<32 | 61441U << 16 | 53404] = // Boomerang
1292  fix[10004LL<<32 | 61441U << 16 | 53408] = // TCM Classic Movies (engl)
1293  fix[10004LL<<32 | 61441U << 16 | 53409] = // Extreme Sports
1294  fix[10004LL<<32 | 61441U << 16 | 53410] = // CNBC Europe (engl)
1295  fix[10004LL<<32 | 61441U << 16 | 53503] = // Detski Mir
1296  fix[10004LL<<32 | 61441U << 16 | 53411] = // Sat.1 Comedy
1297  fix[10004LL<<32 | 61441U << 16 | 53412] = // kabel eins classics
1298  fix[10004LL<<32 | 61441U << 16 | 53112] = // Extreme Sports (engl)
1299  fix[10004LL<<32 | 61441U << 16 | 53513] = // Playhouse Disney (engl)
1300  fix[10004LL<<32 | 61441U << 16 | 53618] = // K1010
1301  fix[10004LL<<32 | 61441U << 16 | 53619] = // GemsTV
1303  // On transport 10005 QVC and Giga Digital needs no fixing:
1304  fix[10005LL<<32 | 61441U << 16 | 50104] = // E! Entertainment
1305  fix[10005LL<<32 | 61441U << 16 | 50107] = // 13th Street (KD)
1306  fix[10005LL<<32 | 61441U << 16 | 50301] = // ESPN Classic
1307  fix[10005LL<<32 | 61441U << 16 | 50302] = // VH1 Classic
1308  fix[10005LL<<32 | 61441U << 16 | 50303] = // Wein TV
1309  fix[10005LL<<32 | 61441U << 16 | 50304] = // AXN
1310  fix[10005LL<<32 | 61441U << 16 | 50305] = // Silverline
1311  fix[10005LL<<32 | 61441U << 16 | 50306] = // NASN
1312  fix[10005LL<<32 | 61441U << 16 | 50307] = // Disney Toon
1313  fix[10005LL<<32 | 61441U << 16 | 53105] = // NASN (engl)
1314  fix[10005LL<<32 | 61441U << 16 | 53115] = // VH1 Classic (engl)
1315  fix[10005LL<<32 | 61441U << 16 | 53405] = // ESPN Classic (engl)
1316  fix[10005LL<<32 | 61441U << 16 | 53402] = // AXN (engl)
1317  fix[10005LL<<32 | 61441U << 16 | 53613] = // CNN (engl)
1318  fix[10005LL<<32 | 61441U << 16 | 53516] = // Voyages Television
1319  fix[10005LL<<32 | 61441U << 16 | 53611] = // Der Schmuckkanal
1320  fix[10005LL<<32 | 61441U << 16 | 53104] = // Jukebox
1322  // On transport 10007 only following channels need fixing:
1323  fix[10007LL<<32| 61441U << 16 | 53607] = // Eurosport
1324  fix[10007LL<<32| 61441U << 16 | 53608] = // Das Vierte
1325  fix[10007LL<<32| 61441U << 16 | 53609] = // Viva
1326  fix[10007LL<<32| 61441U << 16 | 53628] = // COMEDY CENTRAL
1328  // RTL Subtitle parsing
1329  fix[10007LL<<32| 61441U << 16 | 53601] = // RTL
1330  fix[10007LL<<32| 61441U << 16 | 53602] = // Super RTL
1331  fix[10007LL<<32| 61441U << 16 | 53604] = // VOX
1332  fix[10007LL<<32| 61441U << 16 | 53606] = // n-tv
1334  // On transport 10008 only following channels need fixing:
1335  fix[ 10008LL<<32 | 61441U << 16 | 53002] = // Tele 5
1337 
1338  // DVB-C Unitymedia Germany
1339  fix[ 9999 << 16 | 161LL << 32 | 12101 ] = // RTL Television
1340  fix[ 9999 << 16 | 161LL << 32 | 12104 ] = // VOX
1341  fix[ 9999 << 16 | 161LL << 32 | 12107 ] = // Super RTL
1342  fix[ 9999 << 16 | 161LL << 32 | 12109 ] = // n-tv
1343  fix[ 9999 << 16 | 301LL << 32 | 30114 ] = // RTL NITRO
1345  fix[ 9999 << 16 | 191LL << 32 | 11102 ] = // DAS VIERTE
1347  // on this transport are only HD services, two TBD, arte and ServusTV, I think arte properly signals HD!
1348  fix[ 9999 << 16 | 401LL << 32 | 29109 ] = // ServusTV HD
1350  // generic Unitymedia / Liberty Global / Eventis.nl?
1351  fix[ 9999 << 16 | 121LL << 32 | 12107 ] = // Super RTL
1352  fix[ 9999 << 16 | 151LL << 32 | 15110 ] = // Bibel TV
1353  fix[ 9999 << 16 | 161LL << 32 | 12107 ] = // Super RTL
1354  fix[ 9999 << 16 | 161LL << 32 | 12109 ] = // n-tv
1355  fix[ 9999 << 16 | 171LL << 32 | 17119 ] = // RiC
1356  fix[ 9999 << 16 | 171LL << 32 | 27102 ] = // DELUXE MUSIC
1357  fix[ 9999 << 16 | 181LL << 32 | 24108 ] = // DMAX
1358  fix[ 9999 << 16 | 181LL << 32 | 25102 ] = // TV5MONDE Europe
1359  fix[ 9999 << 16 | 191LL << 32 | 11102 ] = // Disney SD
1360  fix[ 9999 << 16 | 191LL << 32 | 12110 ] = // N24
1361  fix[ 9999 << 16 | 191LL << 32 | 12111 ] = // Tele 5
1362  fix[ 9999 << 16 | 201LL << 32 | 27103 ] = // TLC
1363  fix[ 9999 << 16 | 211LL << 32 | 29108 ] = // Astro TV
1364  fix[ 9999 << 16 | 231LL << 32 | 23117 ] = // Deutsches Musik Fernsehen
1365  fix[ 9999 << 16 | 231LL << 32 | 23115 ] = // Family TV
1366  fix[ 9999 << 16 | 271LL << 32 | 27101 ] = // DIE NEUE ZEIT TV
1367  fix[ 9999 << 16 | 541LL << 32 | 54101 ] = // HR HD
1369 
1370  // DVB-S Astra 19.2E DMAX Germany
1371  fix[ 1113LL << 32 | 1 << 16 | 12602] = EITFixUp::kEFixForceISO8859_15;
1372 
1373  // Premiere
1374  fix[133 << 16] = EITFixUp::kEFixForceISO8859_15;
1375 
1376  // DVB-S Astra 19.2E French channels
1377  fix[ 1022LL << 32 | 1 << 16 | 6901 ] = // DIRECT 8
1378  fix[ 1022LL << 32 | 1 << 16 | 6905 ] = // France 24 (en Francais)
1379  fix[ 1022LL << 32 | 1 << 16 | 6911 ] = // DIRECT 8
1380  fix[ 1072LL << 32 | 1 << 16 | 8201 ] = // CANAL+
1381  fix[ 1070LL << 32 | 1 << 16 | 8004 ] = // EURONEWS
1382  fix[ 1091LL << 32 | 1 << 16 | 31220 ] = // EuroNews
1383  fix[ 1094LL << 32 | 1 << 16 | 17027 ] = // LCP
1384  fix[ 1094LL << 32 | 1 << 16 | 17028 ] = // NT1
1385  fix[ 1100LL << 32 | 1 << 16 | 8710 ] = // NRJ 12
1387 
1388  // DVB-C T-Kábel Hungary
1389  // FIXME this should be more specific. Is the encoding really wrong for all services?
1390  fix[ 100 << 16] = EITFixUp::kEFixForceISO8859_2;
1391 
1392  // DVB-T Greece
1393  // Pelion Transmitter
1394  // transport_id<<32 | netword_id<<16 | service_id
1395  fix[ 100LL << 32 | 8492LL << 16 ] = // Ant1,Alpha,Art,10E
1396  fix[ 102LL << 32 | 8492LL << 16 ] = // Mega,Star,SKAI,M.tv
1397  fix[ 320LL << 32 | 8492LL << 16 ] = // Astra,Thessalia,TRT,TV10,ZEYS
1400  fix[ 2LL << 32 | 8492LL << 16 ] = // N1,Nplus,NHD,Vouli
1401  EITFixUp::kEFixForceISO8859_7 | // it is encoded in cp-1253
1402  EITFixUp::kFixGreekSubtitle | // Subtitle has too much info and is
1403  EITFixUp::kFixGreekEIT | // cut in db. Will move to descr.
1405 
1406  // DVB-S Star One C2 70W (Brazil)
1407  // it has original_network_id = 1 like Astra on 19.2E, but transport_id does
1408  // not collide at the moment
1409  fix[ 1LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1410  fix[ 2LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1411  fix[ 3LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1412  fix[ 4LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1413  fix[ 50LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1414  fix[ 51LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1415  fix[ 52LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1416  fix[ 53LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1417  fix[ 54LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1418  fix[ 55LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1419  fix[ 56LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1420  fix[ 57LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1421  fix[ 58LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1422  fix[ 59LL << 32 | 1LL << 16 ] = EITFixUp::kEFixForceISO8859_1;
1423 }
1424 
1430 {
1433  maxStarttime, "EITScanner");
1434  seenEITother = false;
1435  maxStarttime = QDateTime();
1436 }
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:785
QDateTime StartTimeUTC(uint i) const
Definition: dvbtables.h:331
static void parse_dvb_event_descriptors(desc_list_t list, FixupValue fix, QMap< uint, uint > languagePreferences, QString &title, QString &subtitle, QString &description, QMap< QString, QString > &items)
Definition: eithelper.cpp:244
uint TSID(void) const
Definition: dvbtables.h:308
uint GetListSize(void) const
Definition: eithelper.cpp:58
MultipleStringStructure title(int i) const
Definition: atsctables.h:586
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:884
static uint get_chan_id_from_db_dtv(uint sourceid, uint programnumber, uint tunedchanid)
Definition: eithelper.cpp:1013
uint GetChanID(uint atsc_major, uint atsc_minor)
Definition: eithelper.cpp:866
void CompleteEvent(uint atsc_major, uint atsc_minor, const ATSCEvent &event, const QString &ett)
Definition: eithelper.cpp:832
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:83
static void init_fixup(FixupMap &fix)
Definition: eithelper.cpp:1058
const MultipleStringStructure ExtendedTextMessage() const
Definition: atsctables.h:660
QMap< FixupKey, FixupValue > FixupMap
Definition: eithelper.h:77
QMap< uint, uint > languagePreferences
Definition: eithelper.h:158
uint StartTimeRaw(uint i) const
Definition: atsctables.h:560
QString Text(void) const
QString EventName(void) const
const unsigned char * desc
Definition: eithelper.h:41
ExtendedTextTable contain additional text not contained in EventInformationTables.
Definition: atsctables.h:618
const char * subtitles[4]
Definition: vbilut.cpp:202
const unsigned char * Descriptors() const
uint ContentType(size_t n=0) const
QVariant value(int i) const
Definition: mythdbcon.h:182
uint Nibble(uint i) const
uint AudioProperties(uint compression_type) const
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
QString seriesid(void) const
unsigned char VideoProperties(void) const
unsigned char AudioProperties(void) const
uint32_t length
Definition: eithelper.h:37
static uint get_chan_id_from_db_atsc(uint sourceid, uint atscmajor, uint atscminor)
Definition: eithelper.cpp:918
unsigned int uint
Definition: compat.h:136
uint DescriptorsLength(uint i) const
Definition: dvbtables.h:353
static int iso639_str3_to_key(const unsigned char *iso639_2)
Definition: iso639.h:63
static const unsigned char * FindBestMatch(const desc_list_t &parsed, uint desc_tag, QMap< uint, uint > &langPref)
QString GetDescription(uint i) const
vector< const unsigned char * > desc_list_t
int size(void) const
Definition: mythdbcon.h:187
int iso639_key_to_canonical_key(int iso639_2)
Definition: iso639.cpp:122
EITHelper(void)
Definition: eithelper.cpp:40
void SetLanguagePreferences(const QStringList &langPref)
Definition: eithelper.cpp:119
static void TimeFix(QDateTime &dt)
Corrects starttime to the multiple of a minute.
Definition: eitfixup.h:83
QMutex eitList_lock
EIT List lock.
Definition: eithelper.h:138
MythDeque< DBEventEIT * > db_events
Definition: eithelper.h:156
static uint GetMplexID(uint sourceid, const QString &channum)
void enqueue(T d)
Adds item to the back of the list. O(1).
Definition: mythdeque.h:35
QString Name(uint) const
uint DurationInSeconds(uint i) const
Definition: dvbtables.h:342
const unsigned char * Descriptors(uint i) const
Definition: dvbtables.h:357
QString rating(void) const
uint Nibble1(uint i) const
void AddEIT(uint atsc_major, uint atsc_minor, const EventInformationTable *eit)
Definition: eithelper.cpp:148
uint UserNibble(uint i) const
const QString season
Definition: eitfixup.cpp:21
Overall structure.
uint64_t FixupKey
Definition: eithelper.h:75
QString rating(void) const
void Fix(DBEventEIT &event) const
Definition: eitfixup.cpp:244
void WriteEITCache(void)
Definition: eithelper.cpp:823
uint channelid
id of the channel
Definition: eithelper.h:148
ATSCSRCToEvents incomplete_events
Definition: eithelper.h:153
def rating(profile, smoonURL, gate)
Definition: scan.py:25
uint TableID(void) const
Definition: mpegtables.h:479
QString advisory(void) const
QDate originalairdate(void) const
uint32_t start_time
Definition: eithelper.h:36
static EITCache * eitcache
Definition: eithelper.h:142
float stars(void) const
QString Text(void) const
uint EventID(void) const
Definition: atsctables.h:656
QMap< uint, ATSCEtt > EventIDToETT
Definition: eithelper.h:70
void WriteToDB(void)
Definition: eitcache.cpp:298
MBASE_PUBLIC QDateTime fromTime_t(uint seconds)
Definition: mythdate.cpp:60
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
T dequeue()
Removes item from front of list and returns a copy. O(1).
Definition: mythdeque.h:25
uint EventID(uint i) const
Definition: atsctables.h:555
uint SubtitleProperties(uint compression_type) const
void AddETT(uint atsc_major, uint atsc_minor, const ExtendedTextTable *ett)
Definition: eithelper.cpp:193
QString GetBestMatch(QMap< uint, uint > &langPrefs) const
QString Description(uint) const
unsigned char SubtitleType(void) const
int gps_offset
Definition: eithelper.h:144
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:542
EITFixUp * eitfixup
Definition: eithelper.h:141
EIT Fix Up Functions.
Definition: eitfixup.h:15
static void RescheduleMatch(uint recordid, uint sourceid, uint mplexid, const QDateTime &maxstarttime, const QString &why)
void SetSourceID(uint _sourceid)
Definition: eithelper.cpp:136
QString ContentId(size_t n=0) const
static const unsigned char * Find(const desc_list_t &parsed, uint desc_tag)
bool isActive(void) const
Definition: mythdbcon.h:188
EventInformationTables contain program titles, start times, and channel information.
Definition: atsctables.h:518
FixupMap fixup
Definition: eithelper.h:152
uint PruneOldEntries(uint utc_timestamp)
Prunes entries that describe events ending before timestamp time.
Definition: eitcache.cpp:404
ServiceToChanID srv_to_chanid
Definition: eithelper.h:139
ProgramInfo::CategoryType GetMythCategory(uint i) const
bool seenEITother
if false we only reschedule the active mplex
Definition: eithelper.h:150
time_t EndTimeUnixUTC(uint i) const
Definition: dvbtables.h:335
uint32_t desc_length
Definition: eithelper.h:39
static void parse_dvb_component_descriptors(desc_list_t list, unsigned char &subtitle_type, unsigned char &audio_properties, unsigned char &video_properties)
Definition: eithelper.cpp:341
uint sourceid
id of the video source
Definition: eithelper.h:147
bool HasDescription(void) const
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:810
ATSCSRCToETTs unmatched_etts
Definition: eithelper.h:154
QString GetCategory(void) const
uint OriginalNetworkID(void) const
Definition: dvbtables.h:312
bool IsNewEIT(uint chanid, uint tableid, uint version, uint eventid, uint endtime)
Definition: eitcache.cpp:327
uint Nibble2(uint i) const
virtual ~EITHelper(void)
Definition: eithelper.cpp:49
void PruneEITCache(uint timestamp)
Definition: eithelper.cpp:818
uint EventCount() const
Definition: dvbtables.h:322
QDateTime maxStarttime
latest starttime of changed events
Definition: eithelper.h:149
uint ContentEncoding(size_t n=0) const
static const uint kChunkSize
Maximum number of DB inserts per ProcessEvents call.
Definition: eithelper.h:161
uint64_t FixupValue
Definition: eithelper.h:76
QString programid(void) const
QString advisory(void) const
QMap< QString, QString > Items(void) const
uint EventCount() const
Definition: atsctables.h:550
static uint get_chan_id_from_db_dvb(uint sourceid, uint serviceid, uint networkid, uint transportid)
Definition: eithelper.cpp:944
void SetChannelID(uint _channelid)
Definition: eithelper.cpp:142
uint LengthInSeconds(uint i) const
Definition: atsctables.h:577
static const QString LOC
uint32_t PrivateDataSpecifier(void) const
DishThemeType GetTheme(void) const
const unsigned char * Descriptors(uint i) const
Definition: atsctables.h:600
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:610
uint DescriptorsLength(uint i) const
Definition: atsctables.h:592
uint ProcessEvents(void)
Inserts events in EIT list.
Definition: eithelper.cpp:69
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:181
static desc_list_t FindBestMatches(const desc_list_t &parsed, uint desc_tag, QMap< uint, uint > &langPref)
uint ETMLocation(uint i) const
Definition: atsctables.h:572
static desc_list_t FindAll(const desc_list_t &parsed, uint desc_tag)
uint ServiceID(void) const
Definition: dvbtables.h:305
static desc_list_t Parse(const unsigned char *data, uint len)
uint Version(void) const
Definition: mpegtables.h:503
uint EventID(uint i) const
Definition: dvbtables.h:326
bool HasName(void) const
QMap< uint, ATSCEvent > EventIDToATSCEvent
Definition: eithelper.h:69
void RescheduleRecordings(void)
Tells scheduler about programming changes.
Definition: eithelper.cpp:1429
void SetFixup(uint atsc_major, uint atsc_minor, FixupValue eitfixup)
Definition: eithelper.cpp:112