37#define LOC QString("EITHelper: ")
38#define LOC_ID QString("EITHelper[%1]: ").arg(m_cardnum)
46 QString(
"EITHelper chunk size %1 and queue size %2 events")
53 QString(
"EITCache %1")
54 .arg(persistent ?
"in memory, backup to database" :
"in memory only"));
105 insertCount +=
event->UpdateDB(query, 1000);
118 QString(
"Added %1 events -- complete: %2 incomplete: %3")
125 QString(
"Added %1/%2 events, queued: %3")
126 .arg(insertCount).arg(eventCount).arg(
m_dbEvents.size()));
135 FixupKey atsc_key = (atsc_major << 16) | atsc_minor;
144 QStringList::const_iterator it;
145 for (it = langPref.begin(); it != langPref.end(); ++it)
147 if (!(*it).isEmpty())
171 uint atsc_key = (atsc_major << 16) | atsc_minor;
192 EventIDToATSCEvent::iterator it = events.find(eit->
EventID(i));
193 if (it != events.end())
195 delete [] (*it).m_desc;
199 auto *tmp =
new unsigned char[ev.m_descLength];
202 events.insert(eit->
EventID(i), ev);
212 uint atsc_key = (atsc_major << 16) | atsc_minor;
216 EventIDToATSCEvent::iterator it = (*eits_it).find(ett->
EventID());
217 if (it != (*eits_it).end())
220 if (!it->IsStale()) {
222 atsc_major, atsc_minor, *it,
227 delete [] (*it).m_desc;
228 (*eits_it).erase(it);
234 QMap<uint,uint> languagePreferences,
235 QString &title, QString &subtitle,
236 QString &description, QMultiMap<QString,QString> &items)
238 const unsigned char *bestShortEvent =
292 subtitle = sed.
Text(enc);
296 std::vector<const unsigned char*> bestExtendedEvents =
301 for (
auto & best_event : bestExtendedEvents)
312 description += eed.
Text(enc);
315 items.unite (eed.
Items());
320 unsigned char &subtitle_type,
321 unsigned char &audio_properties,
322 unsigned char &video_properties)
326 for (
auto & comp : components)
363 uint descCompression = (eit->
TableID() > 0x80) ? 2 : 1;
385 QString title = QString(
"");
386 QString subtitle = QString(
"");
387 QString description = QString(
"");
388 QString category = QString(
"");
390 unsigned char subtitle_type=0;
391 unsigned char audio_props=0;
392 unsigned char video_props=0;
395 uint totalepisodes = 0;
396 QMultiMap<QString,QString> items;
402 const unsigned char *dish_event_name =
nullptr;
412 if (dend.IsValid() && dend.HasName())
413 title = dend.Name(descCompression);
415 const unsigned char *dish_event_description =
418 if (dish_event_description)
421 if (dedd.IsValid() && dedd.HasDescription())
422 description = dedd.Description(descCompression);
428 title, subtitle, description, items);
434 QString programId = QString(
"");
435 QString seriesId = QString(
"");
436 QString
rating = QString(
"");
437 QString rating_system = QString(
"");
438 QString advisory = QString(
"");
440 QDate originalairdate;
450 stars = mpaa.stars();
455 rating_system =
"MPAA";
456 advisory = mpaa.advisory();
468 rating_system =
"VCHIP";
469 advisory = vchip.advisory();
473 if (!advisory.isEmpty() && !
rating.isEmpty())
475 rating +=
", " + advisory;
477 else if (!advisory.isEmpty())
480 rating_system =
"advisory";
488 seriesId = tags.seriesid();
489 programId = tags.programid();
490 originalairdate = tags.originalairdate();
492 if (programId.startsWith(
"MV") || programId.startsWith(
"SP"))
501 subtitle_type |= properties.SubtitleProperties(descCompression);
502 audio_props |= properties.AudioProperties(descCompression);
506 const unsigned char *content_data =
528 category =
content.GetCategory();
532 static const std::array<const std::string,16> s_auGenres
533 {
"Unknown",
"Movie",
"News",
"Entertainment",
534 "Sport",
"Children",
"Music",
"Arts/Culture",
535 "Current Affairs",
"Education",
"Infotainment",
536 "Special",
"Comedy",
"Drama",
"Documentary",
541 category = QString::fromStdString(s_auGenres[
content.Nibble1(0)]);
542 category_type =
content.GetMythCategory(0);
547 static const std::array<const std::string,16>s_grGenres
548 {
"Unknown",
"Ταινία",
"Ενημερωτικό",
"Unknown",
549 "Αθλητικό",
"Παιδικό",
"Unknown",
"Unknown",
550 "Unknown",
"Ντοκιμαντέρ",
"Unknown",
"Unknown",
551 "Unknown",
"Unknown",
"Unknown",
"Unknown"};
555 category = QString::fromStdString(s_grGenres[
content.Nibble2(0)]);
556 category_type =
content.GetMythCategory(2);
564 category =
content.GetDescription(0);
566 category_type =
content.GetMythCategory(0);
574 for (
auto &
id : contentIds)
579 for (
size_t k = 0; k < desc.CRIDCount(); k++)
581 if (desc.ContentEncoding(k) == 0)
587 if (desc.ContentType(k) == 0x01 || desc.ContentType(k) == 0x31)
589 if (!desc.ContentId(k).startsWith (
"eventis.nl/"))
591 programId = desc.ContentId(k);
594 else if (desc.ContentType(k) == 0x02 || desc.ContentType(k) == 0x32)
596 if (!desc.ContentId(k).startsWith (
"eventis.nl/"))
598 seriesId = desc.ContentId(k);
607 if (subtitle.isEmpty()) {
611 for (
auto & specifier : private_data_specifiers) {
626 subtitle = desc.Text();
640 title, subtitle, description,
641 category, category_type,
642 starttime, endtime, fix,
647 season, episode, totalepisodes);
648 event->m_items = items;
666 QString title = QString(
"");
667 QString subtitle = QString(
"");
668 QString description = QString(
"");
669 QString category = QString(
"");
671 unsigned char subtitle_type=0;
672 unsigned char audio_props=0;
673 unsigned char video_props=0;
676 uint totalepisodes = 0;
677 QMultiMap<QString,QString> items;
684 title, subtitle, description, items);
689 const unsigned char *content_data =
701 else if(
content.UserNibble(0)==0x0)
704 category = QObject::tr(
"Sports");
709 category_type =
content.GetMythCategory(0);
710 category =
content.GetDescription(0);
715 category =
"Unknown";
729 for (
auto & trans : transmissions)
732 if (!transmission.IsValid())
734 uint networkid = transmission.OriginalNetworkID();
735 uint tsid = transmission.TSID();
736 uint serviceid = transmission.ServiceID();
743 QString(
"Premiere EIT for NIT %1, TID %2, SID %3, "
744 "count %4, title: %5. Channel not found!")
745 .arg(networkid).arg(tsid).arg(serviceid)
746 .arg(transmission.TransmissionCount()).arg(title));
756 for (
uint k=0; k<transmission.TransmissionCount(); ++k)
758 QDateTime txstart = transmission.StartTimeUTC(k);
766 title, subtitle, description,
767 category, category_type,
773 season, episode, totalepisodes);
774 event->m_items = items;
814 QDateTime endtime = starttime.addSecs(event.
m_length);
817 unsigned char subtitle_type =
819 SUB_HARDHEAR : SUB_UNKNOWN;
820 unsigned char audio_properties = AUD_UNKNOWN;
821 unsigned char video_properties = VID_UNKNOWN;
823 uint atsc_key = (atsc_major << 16) | atsc_minor;
826 QString title =
event.m_title;
827 const QString& subtitle = ett;
830 m_fixup.value(atsc_key), subtitle_type,
831 audio_properties, video_properties));
840 uint64_t key = sourceid;
841 key |= ((uint64_t) atsc_minor) << 16;
842 key |= ((uint64_t) atsc_major) << 32;
844 ServiceToChanID::const_iterator it =
m_srvToChanid.constFind(key);
860 uint64_t key = sourceid;
861 key |= ((uint64_t) serviceid) << 16;
862 key |= ((uint64_t) networkid) << 32;
863 key |= ((uint64_t) tsid) << 48;
865 ServiceToChanID::const_iterator it =
m_srvToChanid.constFind(key);
881 uint64_t key = sourceid;
882 key |= ((uint64_t) program_number) << 16;
885 ServiceToChanID::const_iterator it =
m_srvToChanid.constFind(key);
900 "SELECT chanid, useonairguide "
902 "WHERE deleted IS NULL AND "
903 " atsc_major_chan = :MAJORCHAN AND "
904 " atsc_minor_chan = :MINORCHAN AND "
905 " sourceid = :SOURCEID");
906 query.
bindValue(
":MAJORCHAN", atsc_major);
907 query.
bindValue(
":MINORCHAN", atsc_minor);
914 else if (query.
next())
916 bool useOnAirGuide = query.
value(1).toBool();
917 return useOnAirGuide ? query.
value(0).toUInt() : 0;
931 "SELECT chanid, useonairguide "
932 "FROM channel, dtv_multiplex "
933 "WHERE deleted IS NULL AND "
934 " serviceid = :SERVICEID AND "
935 " networkid = :NETWORKID AND "
936 " transportid = :TRANSPORTID AND "
937 " channel.sourceid = :SOURCEID AND "
938 " channel.mplexid = dtv_multiplex.mplexid";
941 query.
bindValue(
":SERVICEID", serviceid);
942 query.
bindValue(
":NETWORKID", networkid);
943 query.
bindValue(
":TRANSPORTID", transportid);
952 if (query.
size() > 1)
954 LOG(VB_EIT, LOG_ERR,
LOC +
955 QString(
"Found %1 channels for sourceid %1 networkid %2 "
956 "transportid %3 serviceid %4 but only one expected")
958 .arg(sourceid).arg(networkid).arg(transportid).arg(serviceid));
964 bool useOnAirGuide = query.
value(1).toBool();
965 return useOnAirGuide ? chanid : 0;
970 LOG(VB_EIT, LOG_DEBUG,
LOC +
971 QString(
"No channel found for sourceid %1 networkid %2 "
972 "transportid %3 serviceid %4")
973 .arg(sourceid).arg(networkid).arg(transportid).arg(serviceid));
987 uint db_sourceid = 0;
992 "SELECT c1.chanid, c1.useonairguide, c1.sourceid "
993 "FROM channel c1, dtv_multiplex m, channel c2 "
994 "WHERE c1.deleted IS NULL AND "
995 " c1.serviceid = :SERVICEID AND "
996 " c1.mplexid = m.mplexid AND "
997 " m.mplexid = c2.mplexid AND "
998 " c2.chanid = :CHANID";
1001 query.
bindValue(
":SERVICEID", serviceid);
1002 query.
bindValue(
":CHANID", tunedchanid);
1010 while (query.
next())
1014 bool useOnAirGuide = query.
value(1).toBool();
1015 db_sourceid = query.
value(2).toUInt();
1016 if (sourceid == db_sourceid)
1017 return useOnAirGuide ? chanid : 0;
1020 if (query.
size() > 0)
1022 LOG(VB_EIT, LOG_DEBUG,
1023 LOC + QString(
"Found %1 channels for multiplex of chanid %2, "
1024 "serviceid %3, sourceid %4 in database but none "
1025 "for current sourceid %5.")
1026 .arg(query.
size()).arg(tunedchanid)
1027 .arg(serviceid).arg(db_sourceid).arg(sourceid));
1057 for (
int i = 2001; i <= 2035; ++i)
1062 for (
int i = 2037; i <= 2057; ++i)
1065 for (
int i = 2061; i <= 2069; ++i)
1070 for (
int i = 2089; i <= 2116; ++i)
1084 for (
int i = 2401; i <= 2413; ++i)
1128 fix[ 1089LL << 32 | 1 << 16] =
1129 fix[ 1041LL << 32 | 1 << 16] =
1130 fix[ 1057LL << 32 | 1 << 16] =
1197 fix[ 42249U << 16] =
1265 fix[ 9999 << 16 | 161LL << 32 | 12101 ] =
1266 fix[ 9999 << 16 | 161LL << 32 | 12104 ] =
1267 fix[ 9999 << 16 | 161LL << 32 | 12107 ] =
1268 fix[ 9999 << 16 | 161LL << 32 | 12109 ] =
1269 fix[ 9999 << 16 | 301LL << 32 | 30114 ] =
1271 fix[ 9999 << 16 | 191LL << 32 | 11102 ] =
1274 fix[ 9999 << 16 | 401LL << 32 | 29109 ] =
1277 fix[ 9999 << 16 | 121LL << 32 | 12107 ] =
1278 fix[ 9999 << 16 | 151LL << 32 | 15110 ] =
1279 fix[ 9999 << 16 | 161LL << 32 | 12107 ] =
1280 fix[ 9999 << 16 | 161LL << 32 | 12109 ] =
1281 fix[ 9999 << 16 | 171LL << 32 | 17119 ] =
1282 fix[ 9999 << 16 | 171LL << 32 | 27102 ] =
1283 fix[ 9999 << 16 | 181LL << 32 | 24108 ] =
1284 fix[ 9999 << 16 | 181LL << 32 | 25102 ] =
1285 fix[ 9999 << 16 | 191LL << 32 | 11102 ] =
1286 fix[ 9999 << 16 | 191LL << 32 | 12110 ] =
1287 fix[ 9999 << 16 | 191LL << 32 | 12111 ] =
1288 fix[ 9999 << 16 | 201LL << 32 | 27103 ] =
1289 fix[ 9999 << 16 | 211LL << 32 | 29108 ] =
1290 fix[ 9999 << 16 | 231LL << 32 | 23117 ] =
1291 fix[ 9999 << 16 | 231LL << 32 | 23115 ] =
1292 fix[ 9999 << 16 | 271LL << 32 | 27101 ] =
1293 fix[ 9999 << 16 | 541LL << 32 | 54101 ] =
1303 fix[ 1022LL << 32 | 1 << 16 | 6901 ] =
1304 fix[ 1022LL << 32 | 1 << 16 | 6905 ] =
1305 fix[ 1022LL << 32 | 1 << 16 | 6911 ] =
1306 fix[ 1072LL << 32 | 1 << 16 | 8201 ] =
1307 fix[ 1070LL << 32 | 1 << 16 | 8004 ] =
1308 fix[ 1091LL << 32 | 1 << 16 | 31220 ] =
1309 fix[ 1094LL << 32 | 1 << 16 | 17027 ] =
1310 fix[ 1094LL << 32 | 1 << 16 | 17028 ] =
1311 fix[ 1100LL << 32 | 1 << 16 | 8710 ] =
1321 fix[ 100LL << 32 | 8492LL << 16 ] =
1322 fix[ 102LL << 32 | 8492LL << 16 ] =
1323 fix[ 320LL << 32 | 8492LL << 16 ] =
1327 fix[ 2LL << 32 | 8492LL << 16 ] =
static const std::array< const std::string, 4 > subtitles
const unsigned char * m_desc
static uint GetMplexID(uint sourceid, const QString &channum)
uint VideoProperties(void) const
uint SubtitleType(void) const
uint AudioProperties(void) const
uint PruneOldEntries(uint utc_timestamp)
Prunes entries that describe events ending before timestamp time.
void SetPersistent(bool persistent)
bool IsNewEIT(uint chanid, uint tableid, uint version, uint eventid, uint endtime)
static void TimeFix(QDateTime &dt)
Corrects starttime to the multiple of a minute.
static void Fix(DBEventEIT &event)
void SetSourceID(uint sourceid)
static void PruneEITCache(uint timestamp)
uint GetListSize(void) const
void AddETT(uint, uint, const ExtendedTextTable *)
uint ProcessEvents(void)
Get events from queue and insert into DB after processing.
void SetFixup(uint atsc_major, uint atsc_minor, FixupValue eitfixup)
static EITCache * s_eitCache
static const uint kMaxQueueSize
uint GetChanID(uint atsc_major, uint atsc_minor)
void SetLanguagePreferences(const QStringList &langPref)
ServiceToChanID m_srvToChanid
void CompleteEvent(uint atsc_major, uint atsc_minor, const ATSCEvent &event, const QString &ett)
void RescheduleRecordings(void)
Tells scheduler about programming changes.
static void WriteEITCache(void)
MythDeque< DBEventEIT * > m_dbEvents
ATSCSRCToEvents m_incompleteEvents
QMap< uint, uint > m_languagePreferences
void AddEIT(uint, uint, const EventInformationTable *)
bool EventQueueFull(void) const
void SetChannelID(uint channelid)
QMultiMap< QString, QString > Items(void) const
ExtendedTextTable contain additional text not contained in EventInformationTables.
MultipleStringStructure ExtendedTextMessage() const
static desc_list_t FindAll(const desc_list_t &parsed, uint desc_tag)
static desc_list_t Parse(const unsigned char *data, uint len)
static desc_list_t FindBestMatches(const desc_list_t &parsed, uint desc_tag, QMap< uint, uint > &langPref)
static const unsigned char * FindBestMatch(const desc_list_t &parsed, uint desc_tag, QMap< uint, uint > &langPref)
static const unsigned char * Find(const desc_list_t &parsed, uint desc_tag)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
bool isActive(void) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
QString GetBestMatch(QMap< uint, uint > &langPrefs) const
int GetNumSetting(const QString &key, int defaultval=0)
bool GetBoolSetting(const QString &key, bool defaultval=false)
static void DBError(const QString &where, const MSqlQuery &query)
T dequeue()
Removes item from front of list and returns a copy. O(1).
void enqueue(const T &d)
Adds item to the back of the list. O(1).
const unsigned char * Descriptors() const
uint DescriptorsLength() const
uint ContentID(void) const
uint DurationInSeconds() const
@ upc_event_episode_title
@ premiere_content_transmission
static void RescheduleMatch(uint recordid, uint sourceid, uint mplexid, const QDateTime &maxstarttime, const QString &why)
QString EventName(void) const
std::vector< uint8_t > enc_override
static void parse_dvb_component_descriptors(const desc_list_t &list, unsigned char &subtitle_type, unsigned char &audio_properties, unsigned char &video_properties)
static uint get_chan_id_from_db_dtv(uint sourceid, uint serviceid, uint tunedchanid)
static void init_fixup(FixupMap &fix)
static uint get_chan_id_from_db_atsc(uint sourceid, uint atsc_major, uint atsc_minor)
static uint get_chan_id_from_db_dvb(uint sourceid, uint serviceid, uint networkid, uint transportid)
static void parse_dvb_event_descriptors(const desc_list_t &list, FixupValue fix, QMap< uint, uint > languagePreferences, QString &title, QString &subtitle, QString &description, QMultiMap< QString, QString > &items)
QMap< FixupKey, FixupValue > FixupMap
QMap< uint, ATSCEvent > EventIDToATSCEvent
int iso639_key_to_canonical_key(int iso639_2)
static int iso639_str3_to_key(const unsigned char *iso639_2)
std::vector< const unsigned char * > desc_list_t
static constexpr qint64 GPS_EPOCH
Seconds between start of GPS time and the start of UNIX time.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
MBASE_PUBLIC QDateTime fromSecsSinceEpoch(int64_t seconds)
This function takes the number of seconds since the start of the epoch and returns a QDateTime with t...
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
def rating(profile, smoonURL, gate)