00001
00002
00003
00004 #include <time.h>
00005
00006
00007 #include <algorithm>
00008 using namespace std;
00009
00010
00011 #include "eithelper.h"
00012 #include "eitfixup.h"
00013 #include "eitcache.h"
00014 #include "mythdb.h"
00015 #include "atsctables.h"
00016 #include "dvbtables.h"
00017 #include "premieretables.h"
00018 #include "dishdescriptors.h"
00019 #include "premieredescriptors.h"
00020 #include "mythmiscutil.h"
00021 #include "programdata.h"
00022 #include "programinfo.h"
00023 #include "compat.h"
00024
00025 const uint EITHelper::kChunkSize = 20;
00026 EITCache *EITHelper::eitcache = new EITCache();
00027
00028 static uint get_chan_id_from_db(uint sourceid,
00029 uint atscmajor, uint atscminor);
00030 static uint get_chan_id_from_db(uint sourceid, uint serviceid,
00031 uint networkid, uint transportid);
00032 static void init_fixup(QMap<uint64_t,uint> &fix);
00033 static int calc_eit_utc_offset(void);
00034
00035 #define LOC QString("EITHelper: ")
00036
00037 EITHelper::EITHelper() :
00038 eitfixup(new EITFixUp()),
00039 gps_offset(-1 * GPS_LEAP_SECONDS), utc_offset(0),
00040 sourceid(0)
00041 {
00042 init_fixup(fixup);
00043
00044 utc_offset = calc_eit_utc_offset();
00045
00046 int sign = utc_offset < 0 ? -1 : +1;
00047 int diff = abs(utc_offset);
00048 int hours = diff / (60 * 60);
00049 int minutes = ((diff) / 60) % 60;
00050 int seconds = diff % 60;
00051 LOG(VB_EIT, LOG_INFO, LOC + QString("localtime offset %1%2:%3%4:%5%6 ")
00052 .arg((sign < 0) ? "-" : "")
00053 .arg(hours).arg(minutes/10).arg(minutes%10)
00054 .arg(seconds/10).arg(seconds%10));
00055 }
00056
00057 EITHelper::~EITHelper()
00058 {
00059 QMutexLocker locker(&eitList_lock);
00060 while (db_events.size())
00061 delete db_events.dequeue();
00062
00063 delete eitfixup;
00064 }
00065
00066 uint EITHelper::GetListSize(void) const
00067 {
00068 QMutexLocker locker(&eitList_lock);
00069 return db_events.size();
00070 }
00071
00077 uint EITHelper::ProcessEvents(void)
00078 {
00079 QMutexLocker locker(&eitList_lock);
00080 uint insertCount = 0;
00081
00082 if (!db_events.size())
00083 return 0;
00084
00085 MSqlQuery query(MSqlQuery::InitCon());
00086 for (uint i = 0; (i < kChunkSize) && (db_events.size() > 0); i++)
00087 {
00088 DBEventEIT *event = db_events.dequeue();
00089 eitList_lock.unlock();
00090
00091 eitfixup->Fix(*event);
00092
00093 insertCount += event->UpdateDB(query, 1000);
00094
00095 delete event;
00096 eitList_lock.lock();
00097 }
00098
00099 if (!insertCount)
00100 return 0;
00101
00102 if (incomplete_events.size() || unmatched_etts.size())
00103 {
00104 LOG(VB_EIT, LOG_INFO,
00105 LOC + QString("Added %1 events -- complete(%2) "
00106 "incomplete(%3) unmatched(%4)")
00107 .arg(insertCount).arg(db_events.size())
00108 .arg(incomplete_events.size()).arg(unmatched_etts.size()));
00109 }
00110 else
00111 {
00112 LOG(VB_EIT, LOG_INFO,
00113 LOC + QString("Added %1 events").arg(insertCount));
00114 }
00115
00116 return insertCount;
00117 }
00118
00119 void EITHelper::SetFixup(uint atsc_major, uint atsc_minor, uint eitfixup)
00120 {
00121 QMutexLocker locker(&eitList_lock);
00122 uint atsc_key = (atsc_major << 16) | atsc_minor;
00123 fixup[atsc_key] = eitfixup;
00124 }
00125
00126 void EITHelper::SetLanguagePreferences(const QStringList &langPref)
00127 {
00128 QMutexLocker locker(&eitList_lock);
00129
00130 uint priority = 1;
00131 QStringList::const_iterator it;
00132 for (it = langPref.begin(); it != langPref.end(); ++it)
00133 {
00134 if (!(*it).isEmpty())
00135 {
00136 uint language_key = iso639_str3_to_key(*it);
00137 uint canonoical_key = iso639_key_to_canonical_key(language_key);
00138 languagePreferences[canonoical_key] = priority++;
00139 }
00140 }
00141 }
00142
00143 void EITHelper::SetSourceID(uint _sourceid)
00144 {
00145 QMutexLocker locker(&eitList_lock);
00146 sourceid = _sourceid;
00147 }
00148
00149 void EITHelper::AddEIT(uint atsc_major, uint atsc_minor,
00150 const EventInformationTable *eit)
00151 {
00152 uint atsc_key = (atsc_major << 16) | atsc_minor;
00153 EventIDToATSCEvent &events = incomplete_events[atsc_key];
00154 EventIDToETT &etts = unmatched_etts[atsc_key];
00155
00156 for (uint i = 0; i < eit->EventCount(); i++)
00157 {
00158 ATSCEvent ev(eit->StartTimeRaw(i), eit->LengthInSeconds(i),
00159 eit->ETMLocation(i),
00160 eit->title(i).GetBestMatch(languagePreferences),
00161 eit->Descriptors(i), eit->DescriptorsLength(i));
00162
00163 EventIDToETT::iterator it = etts.find(eit->EventID(i));
00164
00165 if (it != etts.end())
00166 {
00167 CompleteEvent(atsc_major, atsc_minor, ev, *it);
00168 etts.erase(it);
00169 }
00170 else if (!ev.etm)
00171 {
00172 CompleteEvent(atsc_major, atsc_minor, ev, QString::null);
00173 }
00174 else
00175 {
00176 unsigned char *tmp = new unsigned char[ev.desc_length];
00177 memcpy(tmp, eit->Descriptors(i), ev.desc_length);
00178 ev.desc = tmp;
00179 events[eit->EventID(i)] = ev;
00180 }
00181 }
00182 }
00183
00184 void EITHelper::AddETT(uint atsc_major, uint atsc_minor,
00185 const ExtendedTextTable *ett)
00186 {
00187 uint atsc_key = (atsc_major << 16) | atsc_minor;
00188
00189 ATSCSRCToEvents::iterator eits_it = incomplete_events.find(atsc_key);
00190 if (eits_it != incomplete_events.end())
00191 {
00192 EventIDToATSCEvent::iterator it = (*eits_it).find(ett->EventID());
00193 if (it != (*eits_it).end())
00194 {
00195 CompleteEvent(
00196 atsc_major, atsc_minor, *it,
00197 ett->ExtendedTextMessage().GetBestMatch(languagePreferences));
00198
00199 if ((*it).desc)
00200 delete [] (*it).desc;
00201
00202 (*eits_it).erase(it);
00203
00204 return;
00205 }
00206 }
00207
00208
00209 EventIDToETT &elist = unmatched_etts[atsc_key];
00210 if (elist.find(ett->EventID()) == elist.end())
00211 {
00212 elist[ett->EventID()] = ett->ExtendedTextMessage()
00213 .GetBestMatch(languagePreferences);
00214 }
00215 }
00216
00217 static void parse_dvb_event_descriptors(desc_list_t list, uint fix,
00218 QMap<uint,uint> languagePreferences,
00219 QString &title, QString &subtitle,
00220 QString &description)
00221 {
00222 const unsigned char *bestShortEvent =
00223 MPEGDescriptor::FindBestMatch(
00224 list, DescriptorID::short_event, languagePreferences);
00225
00226 unsigned char enc_1[3] = { 0x10, 0x00, 0x01 };
00227 unsigned char enc_15[3] = { 0x10, 0x00, 0x0f };
00228 int enc_len = 0;
00229 const unsigned char *enc = NULL;
00230
00231
00232
00233 if (fix & EITFixUp::kEFixForceISO8859_1)
00234 {
00235 enc = enc_1;
00236 enc_len = sizeof(enc_1);
00237 }
00238
00239
00240
00241 if (fix & EITFixUp::kEFixForceISO8859_15)
00242 {
00243 enc = enc_15;
00244 enc_len = sizeof(enc_15);
00245 }
00246
00247 if (bestShortEvent)
00248 {
00249 ShortEventDescriptor sed(bestShortEvent);
00250 if (enc)
00251 {
00252 title = sed.EventName(enc, enc_len);
00253 subtitle = sed.Text(enc, enc_len);
00254 }
00255 else
00256 {
00257 title = sed.EventName();
00258 subtitle = sed.Text();
00259 }
00260 }
00261
00262 vector<const unsigned char*> bestExtendedEvents =
00263 MPEGDescriptor::FindBestMatches(
00264 list, DescriptorID::extended_event, languagePreferences);
00265
00266 description = "";
00267 for (uint j = 0; j < bestExtendedEvents.size(); j++)
00268 {
00269 if (!bestExtendedEvents[j])
00270 {
00271 description = "";
00272 break;
00273 }
00274
00275 ExtendedEventDescriptor eed(bestExtendedEvents[j]);
00276 if (enc)
00277 description += eed.Text(enc, enc_len);
00278 else
00279 description += eed.Text();
00280 }
00281 }
00282
00283 static inline void parse_dvb_component_descriptors(desc_list_t list,
00284 unsigned char &subtitle_type,
00285 unsigned char &audio_properties,
00286 unsigned char &video_properties)
00287 {
00288 desc_list_t components =
00289 MPEGDescriptor::FindAll(list, DescriptorID::component);
00290 for (uint j = 0; j < components.size(); j++)
00291 {
00292 ComponentDescriptor component(components[j]);
00293 video_properties |= component.VideoProperties();
00294 audio_properties |= component.AudioProperties();
00295 subtitle_type |= component.SubtitleType();
00296 }
00297 }
00298
00299 void EITHelper::AddEIT(const DVBEventInformationTable *eit)
00300 {
00301 uint descCompression = (eit->TableID() > 0x80) ? 2 : 1;
00302 uint fix = fixup.value(eit->OriginalNetworkID() << 16);
00303 fix |= fixup.value((((uint64_t)eit->TSID()) << 32) |
00304 (eit->OriginalNetworkID() << 16));
00305 fix |= fixup.value((eit->OriginalNetworkID() << 16) | eit->ServiceID());
00306 fix |= fixup.value((((uint64_t)eit->TSID()) << 32) |
00307 (uint64_t)(eit->OriginalNetworkID() << 16) |
00308 (uint64_t)eit->ServiceID());
00309 fix |= EITFixUp::kFixGenericDVB;
00310
00311 uint chanid = GetChanID(eit->ServiceID(), eit->OriginalNetworkID(),
00312 eit->TSID());
00313 if (!chanid)
00314 return;
00315
00316 uint tableid = eit->TableID();
00317 uint version = eit->Version();
00318 for (uint i = 0; i < eit->EventCount(); i++)
00319 {
00320
00321 if (!eitcache->IsNewEIT(chanid, tableid, version, eit->EventID(i),
00322 eit->EndTimeUnixUTC(i)))
00323 {
00324 continue;
00325 }
00326
00327 QString title = QString("");
00328 QString subtitle = QString("");
00329 QString description = QString("");
00330 QString category = QString("");
00331 uint category_type = kCategoryNone;
00332 unsigned char subtitle_type=0, audio_props=0, video_props=0;
00333
00334
00335 desc_list_t list = MPEGDescriptor::Parse(
00336 eit->Descriptors(i), eit->DescriptorsLength(i));
00337
00338 const unsigned char *dish_event_name = NULL;
00339 if (EITFixUp::kFixDish & fix)
00340 {
00341 dish_event_name = MPEGDescriptor::Find(
00342 list, PrivateDescriptorID::dish_event_name);
00343 }
00344
00345 if (dish_event_name)
00346 {
00347 DishEventNameDescriptor dend(dish_event_name);
00348 if (dend.HasName())
00349 title = dend.Name(descCompression);
00350
00351 const unsigned char *dish_event_description =
00352 MPEGDescriptor::Find(
00353 list, PrivateDescriptorID::dish_event_description);
00354 if (dish_event_description)
00355 {
00356 DishEventDescriptionDescriptor dedd(dish_event_description);
00357 if (dedd.HasDescription())
00358 description = dedd.Description(descCompression);
00359 }
00360 }
00361 else
00362 {
00363 parse_dvb_event_descriptors(list, fix, languagePreferences,
00364 title, subtitle, description);
00365 }
00366
00367 parse_dvb_component_descriptors(list, subtitle_type, audio_props,
00368 video_props);
00369
00370 QString programId = QString("");
00371 QString seriesId = QString("");
00372 QString rating = QString("");
00373 QString rating_system = QString("");
00374 QString advisory = QString("");
00375 float stars = 0.0;
00376 QDate originalairdate;
00377
00378 if (EITFixUp::kFixDish & fix)
00379 {
00380 const unsigned char *mpaa_data = MPEGDescriptor::Find(
00381 list, PrivateDescriptorID::dish_event_mpaa);
00382 if (mpaa_data)
00383 {
00384 DishEventMPAADescriptor mpaa(mpaa_data);
00385 stars = mpaa.stars();
00386
00387 if (stars)
00388 {
00389 rating = mpaa.rating();
00390 rating_system = "MPAA";
00391 advisory = mpaa.advisory();
00392 }
00393 }
00394
00395 if (!stars)
00396 {
00397 const unsigned char *vchip_data = MPEGDescriptor::Find(
00398 list, PrivateDescriptorID::dish_event_vchip);
00399 if (vchip_data)
00400 {
00401 DishEventVCHIPDescriptor vchip(vchip_data);
00402 rating = vchip.rating();
00403 rating_system = "VCHIP";
00404 advisory = vchip.advisory();
00405 }
00406 }
00407
00408 if (!advisory.isEmpty() && !rating.isEmpty())
00409 rating += ", " + advisory;
00410 else if (!advisory.isEmpty())
00411 {
00412 rating = advisory;
00413 rating_system = "advisory";
00414 }
00415
00416 const unsigned char *tags_data = MPEGDescriptor::Find(
00417 list, PrivateDescriptorID::dish_event_tags);
00418 if (tags_data)
00419 {
00420 DishEventTagsDescriptor tags(tags_data);
00421 seriesId = tags.seriesid();
00422 programId = tags.programid();
00423 originalairdate = tags.originalairdate();
00424
00425 if (programId.startsWith("MV") || programId.startsWith("SP"))
00426 seriesId = "";
00427 }
00428
00429 const unsigned char *properties_data = MPEGDescriptor::Find(
00430 list, PrivateDescriptorID::dish_event_properties);
00431 if (properties_data)
00432 {
00433 DishEventPropertiesDescriptor properties(properties_data);
00434 subtitle_type |= properties.SubtitleProperties(descCompression);
00435 audio_props |= properties.AudioProperties(descCompression);
00436 }
00437 }
00438
00439 const unsigned char *content_data =
00440 MPEGDescriptor::Find(list, DescriptorID::content);
00441 if (content_data)
00442 {
00443 if ((EITFixUp::kFixDish & fix) || (EITFixUp::kFixBell & fix))
00444 {
00445 DishContentDescriptor content(content_data);
00446 category_type = content.GetTheme();
00447 if (EITFixUp::kFixDish & fix)
00448 category = content.GetCategory();
00449 }
00450 else
00451 {
00452 ContentDescriptor content(content_data);
00453 category = content.GetDescription(0);
00454 category_type = content.GetMythCategory(0);
00455 }
00456 }
00457
00458 desc_list_t contentIds =
00459 MPEGDescriptor::FindAll(list, DescriptorID::dvb_content_identifier);
00460 for (uint j = 0; j < contentIds.size(); j++)
00461 {
00462 DVBContentIdentifierDescriptor desc(contentIds[j]);
00463 if (desc.ContentEncoding() == 0)
00464 {
00465
00466
00467
00468 if (desc.ContentType() == 0x01 || desc.ContentType() == 0x31)
00469 programId = desc.ContentId();
00470 else if (desc.ContentType() == 0x02 || desc.ContentType() == 0x32)
00471 seriesId = desc.ContentId();
00472 }
00473 }
00474
00475 QDateTime starttime = MythUTCToLocal(eit->StartTimeUTC(i));
00476
00477 if (!(eit->DurationInSeconds(i) % 60))
00478 EITFixUp::TimeFix(starttime);
00479 QDateTime endtime = starttime.addSecs(eit->DurationInSeconds(i));
00480
00481 DBEventEIT *event = new DBEventEIT(
00482 chanid,
00483 title, subtitle, description,
00484 category, category_type,
00485 starttime, endtime, fix,
00486 subtitle_type,
00487 audio_props,
00488 video_props, stars,
00489 seriesId, programId);
00490
00491 db_events.enqueue(event);
00492 }
00493 }
00494
00495
00496
00497 void EITHelper::AddEIT(const PremiereContentInformationTable *cit)
00498 {
00499
00500 uint fix = fixup.value(133 << 16);
00501 fix |= EITFixUp::kFixGenericDVB;
00502
00503 QString title = QString("");
00504 QString subtitle = QString("");
00505 QString description = QString("");
00506 QString category = QString("");
00507 MythCategoryType category_type = kCategoryNone;
00508 unsigned char subtitle_type=0, audio_props=0, video_props=0;
00509
00510
00511 desc_list_t list = MPEGDescriptor::Parse(
00512 cit->Descriptors(), cit->DescriptorsLength());
00513
00514 parse_dvb_event_descriptors(list, fix, languagePreferences,
00515 title, subtitle, description);
00516
00517 parse_dvb_component_descriptors(list, subtitle_type, audio_props,
00518 video_props);
00519
00520 const unsigned char *content_data =
00521 MPEGDescriptor::Find(list, DescriptorID::content);
00522 if (content_data)
00523 {
00524 ContentDescriptor content(content_data);
00525
00526 if (content.Nibble(0)==0x00)
00527 {
00528 if(content.UserNibble(0)==0x1)
00529 {
00530 category_type = kCategoryMovie;
00531 }
00532 else if(content.UserNibble(0)==0x0)
00533 {
00534 category_type = kCategorySports;
00535 category = QObject::tr("Sports");
00536 }
00537 }
00538 else
00539 {
00540 category_type = content.GetMythCategory(0);
00541 category = content.GetDescription(0);
00542 }
00543 }
00544
00545 uint tableid = cit->TableID();
00546 uint version = cit->Version();
00547 uint contentid = cit->ContentID();
00548
00549 uint endtime = QDateTime::currentDateTime().addDays(1).toTime_t();
00550
00551
00552 desc_list_t transmissions =
00553 MPEGDescriptor::FindAll(
00554 list, PrivateDescriptorID::premiere_content_transmission);
00555 for(uint j=0; j< transmissions.size(); j++)
00556 {
00557 PremiereContentTransmissionDescriptor transmission(transmissions[j]);
00558 uint networkid = transmission.OriginalNetworkID();
00559 uint tsid = transmission.TSID();
00560 uint serviceid = transmission.ServiceID();
00561
00562 uint chanid = GetChanID(serviceid, networkid, tsid);
00563
00564 if (!chanid)
00565 {
00566 LOG(VB_EIT, LOG_INFO, LOC +
00567 QString("Premiere EIT for NIT %1, TID %2, SID %3, "
00568 "count %4, title: %5. Channel not found!")
00569 .arg(networkid).arg(tsid).arg(serviceid)
00570 .arg(transmission.TransmissionCount()).arg(title));
00571 continue;
00572 }
00573
00574
00575 if (!eitcache->IsNewEIT(chanid, tableid, version, contentid, endtime))
00576 {
00577 continue;
00578 }
00579
00580 for (uint k=0; k<transmission.TransmissionCount(); ++k)
00581 {
00582 QDateTime starttime = transmission.StartTimeUTC(k);
00583
00584 if (!(cit->DurationInSeconds() % 60))
00585 EITFixUp::TimeFix(starttime);
00586 QDateTime endtime = starttime.addSecs(cit->DurationInSeconds());
00587
00588 DBEventEIT *event = new DBEventEIT(
00589 chanid,
00590 title, subtitle, description,
00591 category, category_type,
00592 starttime, endtime, fix,
00593 subtitle_type,
00594 audio_props,
00595 video_props, 0.0,
00596 "", "");
00597
00598 db_events.enqueue(event);
00599 }
00600 }
00601 }
00602
00603
00604 void EITHelper::PruneEITCache(uint timestamp)
00605 {
00606 eitcache->PruneOldEntries(timestamp);
00607 }
00608
00609 void EITHelper::WriteEITCache(void)
00610 {
00611 eitcache->WriteToDB();
00612 }
00613
00615
00617
00618 void EITHelper::CompleteEvent(uint atsc_major, uint atsc_minor,
00619 const ATSCEvent &event,
00620 const QString &ett)
00621 {
00622 uint chanid = GetChanID(atsc_major, atsc_minor);
00623 if (!chanid)
00624 return;
00625
00626 QDateTime starttime;
00627 time_t off = GPS_EPOCH + gps_offset + utc_offset;
00628 time_t tmp = event.start_time + off;
00629 tm result;
00630
00631 if (gmtime_r(&tmp, &result))
00632 {
00633 starttime.setDate(QDate(result.tm_year + 1900,
00634 result.tm_mon + 1,
00635 result.tm_mday));
00636 starttime.setTime(QTime(result.tm_hour, result.tm_min, result.tm_sec));
00637 }
00638 else
00639 {
00640 starttime.setTime_t(tmp - utc_offset);
00641 }
00642
00643
00644 if (!(event.length % 60))
00645 EITFixUp::TimeFix(starttime);
00646 QDateTime endtime = starttime.addSecs(event.length);
00647
00648 desc_list_t list = MPEGDescriptor::Parse(event.desc, event.desc_length);
00649 unsigned char subtitle_type =
00650 MPEGDescriptor::Find(list, DescriptorID::caption_service) ?
00651 SUB_HARDHEAR : SUB_UNKNOWN;
00652 unsigned char audio_properties = AUD_UNKNOWN;
00653 unsigned char video_properties = VID_UNKNOWN;
00654
00655 uint atsc_key = (atsc_major << 16) | atsc_minor;
00656
00657 QMutexLocker locker(&eitList_lock);
00658 QString title = event.title;
00659 QString subtitle = ett;
00660 db_events.enqueue(new DBEventEIT(chanid, title, subtitle,
00661 starttime, endtime,
00662 fixup.value(atsc_key), subtitle_type,
00663 audio_properties, video_properties));
00664 }
00665
00666 uint EITHelper::GetChanID(uint atsc_major, uint atsc_minor)
00667 {
00668 uint64_t key;
00669 key = ((uint64_t) sourceid);
00670 key |= ((uint64_t) atsc_minor) << 16;
00671 key |= ((uint64_t) atsc_major) << 32;
00672
00673 ServiceToChanID::const_iterator it = srv_to_chanid.find(key);
00674 if (it != srv_to_chanid.end())
00675 return max(*it, 0);
00676
00677 uint chanid = get_chan_id_from_db(sourceid, atsc_major, atsc_minor);
00678 if (chanid)
00679 srv_to_chanid[key] = chanid;
00680
00681 return chanid;
00682 }
00683
00684 uint EITHelper::GetChanID(uint serviceid, uint networkid, uint tsid)
00685 {
00686 uint64_t key;
00687 key = ((uint64_t) sourceid);
00688 key |= ((uint64_t) serviceid) << 16;
00689 key |= ((uint64_t) networkid) << 32;
00690 key |= ((uint64_t) tsid) << 48;
00691
00692 ServiceToChanID::const_iterator it = srv_to_chanid.find(key);
00693 if (it != srv_to_chanid.end())
00694 return max(*it, 0);
00695
00696 uint chanid = get_chan_id_from_db(sourceid, serviceid, networkid, tsid);
00697 if (chanid)
00698 srv_to_chanid[key] = chanid;
00699
00700 return chanid;
00701 }
00702
00703 static uint get_chan_id_from_db(uint sourceid,
00704 uint atsc_major, uint atsc_minor)
00705 {
00706 MSqlQuery query(MSqlQuery::InitCon());
00707 query.prepare(
00708 "SELECT chanid, useonairguide "
00709 "FROM channel "
00710 "WHERE atsc_major_chan = :MAJORCHAN AND "
00711 " atsc_minor_chan = :MINORCHAN AND "
00712 " sourceid = :SOURCEID");
00713 query.bindValue(":MAJORCHAN", atsc_major);
00714 query.bindValue(":MINORCHAN", atsc_minor);
00715 query.bindValue(":SOURCEID", sourceid);
00716
00717 if (!query.exec() || !query.isActive())
00718 MythDB::DBError("Looking up chanid 1", query);
00719 else if (query.next())
00720 {
00721 bool useOnAirGuide = query.value(1).toBool();
00722 return (useOnAirGuide) ? query.value(0).toUInt() : 0;
00723 }
00724
00725 return 0;
00726 }
00727
00728
00729 static uint get_chan_id_from_db(uint sourceid, uint serviceid,
00730 uint networkid, uint transportid)
00731 {
00732 uint chanid = 0;
00733 bool useOnAirGuide = false;
00734 MSqlQuery query(MSqlQuery::InitCon());
00735
00736
00737 QString qstr =
00738 "SELECT chanid, useonairguide, channel.sourceid "
00739 "FROM channel, dtv_multiplex "
00740 "WHERE serviceid = :SERVICEID AND "
00741 " networkid = :NETWORKID AND "
00742 " transportid = :TRANSPORTID AND "
00743 " channel.mplexid = dtv_multiplex.mplexid";
00744
00745 query.prepare(qstr);
00746 query.bindValue(":SERVICEID", serviceid);
00747 query.bindValue(":NETWORKID", networkid);
00748 query.bindValue(":TRANSPORTID", transportid);
00749
00750 if (!query.exec() || !query.isActive())
00751 MythDB::DBError("Looking up chanID", query);
00752
00753 while (query.next())
00754 {
00755
00756 chanid = query.value(0).toUInt();
00757 useOnAirGuide = query.value(1).toBool();
00758 if (sourceid == query.value(2).toUInt())
00759 return useOnAirGuide ? chanid : 0;
00760 }
00761
00762 if (query.size() > 1) {
00763 LOG(VB_EIT, LOG_INFO,
00764 LOC + QString("found %1 channels for networdid %2, "
00765 "transportid %3, serviceid %4 but none "
00766 "for current sourceid %5.")
00767 .arg(query.size()).arg(networkid).arg(transportid)
00768 .arg(serviceid).arg(sourceid));
00769 }
00770
00771 return useOnAirGuide ? chanid : 0;
00772 }
00773
00774 static void init_fixup(QMap<uint64_t,uint> &fix)
00775 {
00777
00778
00779
00780
00781 fix[ 256U << 16] = EITFixUp::kFixBell;
00782 fix[ 257U << 16] = EITFixUp::kFixBell;
00783 fix[ 4100U << 16] = EITFixUp::kFixBell;
00784 fix[ 4101U << 16] = EITFixUp::kFixBell;
00785 fix[ 4102U << 16] = EITFixUp::kFixBell;
00786 fix[ 4103U << 16] = EITFixUp::kFixBell;
00787 fix[ 4104U << 16] = EITFixUp::kFixBell;
00788 fix[ 4105U << 16] = EITFixUp::kFixBell;
00789 fix[ 4106U << 16] = EITFixUp::kFixBell;
00790 fix[ 4107U << 16] = EITFixUp::kFixBell;
00791 fix[ 4097U << 16] = EITFixUp::kFixBell;
00792 fix[ 4098U << 16] = EITFixUp::kFixBell;
00793
00794
00795 fix[ 9018U << 16] = EITFixUp::kFixUK;
00796
00797 fix[ 2013LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00798 fix[ 2041LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00799 fix[ 2042LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00800 fix[ 2044LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00801 fix[ 2045LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00802 fix[ 2046LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00803 fix[ 2047LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00804 fix[ 2048LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00805 fix[ 2049LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00806 fix[ 2050LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00807 fix[ 2051LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00808 fix[ 2053LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00809 fix[ 2054LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00810 fix[ 2056LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00811 fix[ 2057LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00812 fix[ 2063LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00813 fix[ 2068LL << 32 | 2U << 16] = EITFixUp::kFixUK;
00814
00815
00816 fix[40999U << 16 ] = EITFixUp::kFixComHem;
00817 fix[40999U << 16 | 1070] = EITFixUp::kFixSubtitle;
00818 fix[40999U << 16 | 1308] = EITFixUp::kFixSubtitle;
00819 fix[40999U << 16 | 1041] = EITFixUp::kFixSubtitle;
00820 fix[40999U << 16 | 1306] = EITFixUp::kFixSubtitle;
00821 fix[40999U << 16 | 1307] = EITFixUp::kFixSubtitle;
00822 fix[40999U << 16 | 1030] = EITFixUp::kFixSubtitle;
00823 fix[40999U << 16 | 1016] = EITFixUp::kFixSubtitle;
00824 fix[40999U << 16 | 1131] = EITFixUp::kFixSubtitle;
00825 fix[40999U << 16 | 1068] = EITFixUp::kFixSubtitle;
00826 fix[40999U << 16 | 1069] = EITFixUp::kFixSubtitle;
00827
00828
00829 fix[ 4096U << 16] = EITFixUp::kFixAUStar;
00830 fix[ 4096U << 16] = EITFixUp::kFixAUStar;
00831
00832
00833 fix[ 6144U << 16] = EITFixUp::kFixMCA;
00834
00835
00836 fix[ 1089LL << 32 | 1 << 16] =
00837 fix[ 773LL << 32 | 8468U << 16] =
00838 fix[ 2819LL << 32 | 8468U << 16] =
00839 fix[ 8706LL << 32 | 8468U << 16] =
00840 fix[ 12801LL << 32 | 8468U << 16] =
00841 EITFixUp::kFixRTL | EITFixUp::kFixCategory;
00842
00843
00844 fix[ 1LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
00845 fix[ 2LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
00846 fix[ 3LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
00847 fix[ 4LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
00848 fix[ 5LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
00849 fix[ 6LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
00850 fix[ 17LL << 32 | 133 << 16] = EITFixUp::kFixPremiere;
00851
00852 fix[ 6LL << 32 | 133 << 16 | 129] = EITFixUp::kFixHDTV;
00853 fix[ 6LL << 32 | 133 << 16 | 130] = EITFixUp::kFixHDTV;
00854
00855
00856 fix[ 1000U << 16] = EITFixUp::kFixNL;
00857
00858
00859 fix[ 8438U << 16] =
00860 fix[ 42249U << 16] =
00861 fix[ 15U << 16] =
00862 EITFixUp::kFixFI | EITFixUp::kFixCategory;
00863
00864
00865 fix[70U << 16] = EITFixUp::kFixNO;
00866
00867
00868 fix[910LL << 32 | 8770U << 16 | 0x006f] = EITFixUp::kFixNRK_DVBT;
00869 fix[910LL << 32 | 8770U << 16 | 0x0070] = EITFixUp::kFixNRK_DVBT;
00870 fix[910LL << 32 | 8770U << 16 | 0x0071] = EITFixUp::kFixNRK_DVBT;
00871 fix[910LL << 32 | 8770U << 16 | 0x0072] = EITFixUp::kFixNRK_DVBT;
00872 fix[910LL << 32 | 8770U << 16 | 0x0073] = EITFixUp::kFixNRK_DVBT;
00873 fix[910LL << 32 | 8770U << 16 | 0x0074] = EITFixUp::kFixNRK_DVBT;
00874 fix[910LL << 32 | 8770U << 16 | 0x0067] = EITFixUp::kFixNRK_DVBT;
00875 fix[910LL << 32 | 8770U << 16 | 0x0068] = EITFixUp::kFixNRK_DVBT;
00876 fix[910LL << 32 | 8770U << 16 | 0x0069] = EITFixUp::kFixNRK_DVBT;
00877 fix[910LL << 32 | 8770U << 16 | 0x006a] = EITFixUp::kFixNRK_DVBT;
00878 fix[910LL << 32 | 8770U << 16 | 0x006b] = EITFixUp::kFixNRK_DVBT;
00879 fix[910LL << 32 | 8770U << 16 | 0x006c] = EITFixUp::kFixNRK_DVBT;
00880 fix[910LL << 32 | 8770U << 16 | 0x006d] = EITFixUp::kFixNRK_DVBT;
00881 fix[910LL << 32 | 8770U << 16 | 0x006e] = EITFixUp::kFixNRK_DVBT;
00882 fix[910LL << 32 | 8770U << 16 | 0x0066] = EITFixUp::kFixNRK_DVBT;
00883 fix[910LL << 32 | 8770U << 16 | 0x03f0] = EITFixUp::kFixNRK_DVBT;
00884 fix[910LL << 32 | 8770U << 16 | 0x0455] = EITFixUp::kFixNRK_DVBT;
00885 fix[910LL << 32 | 8770U << 16 | 0x03f1] = EITFixUp::kFixNRK_DVBT;
00886
00888
00889
00890
00891
00892 fix[ 256U << 16] |= EITFixUp::kEFixForceISO8859_1;
00893 fix[ 257U << 16] |= EITFixUp::kEFixForceISO8859_1;
00894 fix[4100U << 16] |= EITFixUp::kEFixForceISO8859_1;
00895 fix[4101U << 16] |= EITFixUp::kEFixForceISO8859_1;
00896 fix[4102U << 16] |= EITFixUp::kEFixForceISO8859_1;
00897 fix[4103U << 16] |= EITFixUp::kEFixForceISO8859_1;
00898 fix[4104U << 16] |= EITFixUp::kEFixForceISO8859_1;
00899 fix[4105U << 16] |= EITFixUp::kEFixForceISO8859_1;
00900 fix[4106U << 16] |= EITFixUp::kEFixForceISO8859_1;
00901 fix[4107U << 16] |= EITFixUp::kEFixForceISO8859_1;
00902 fix[4097U << 16] |= EITFixUp::kEFixForceISO8859_1;
00903 fix[4098U << 16] |= EITFixUp::kEFixForceISO8859_1;
00904
00905
00906 fix[ 772LL << 32 | 8468 << 16 | 16387] = EITFixUp::kEFixForceISO8859_15;
00907
00908 fix[ 8707LL << 32 | 8468 << 16 | 16413] = EITFixUp::kEFixForceISO8859_15;
00909
00910
00911 fix[ 112LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
00912 fix[ 10000LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
00913 fix[ 10001LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
00914 fix[ 10002LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
00915 fix[ 10003LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
00916 fix[ 10006LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
00917 fix[ 10009LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
00918 fix[ 10010LL << 32 | 61441U << 16] = EITFixUp::kEFixForceISO8859_15;
00919
00920 fix[ 10012LL << 32 | 61441U << 16] = EITFixUp::kFixHDTV;
00921 fix[ 10013LL << 32 | 61441U << 16] = EITFixUp::kFixHDTV;
00922
00923 fix[10004LL<<32 | 61441U << 16 | 50403] =
00924 fix[10004LL<<32 | 61441U << 16 | 53101] =
00925 fix[10004LL<<32 | 61441U << 16 | 53108] =
00926 fix[10004LL<<32 | 61441U << 16 | 53109] =
00927 fix[10004LL<<32 | 61441U << 16 | 53406] =
00928 fix[10004LL<<32 | 61441U << 16 | 53407] =
00929 fix[10004LL<<32 | 61441U << 16 | 53404] =
00930 fix[10004LL<<32 | 61441U << 16 | 53408] =
00931 fix[10004LL<<32 | 61441U << 16 | 53409] =
00932 fix[10004LL<<32 | 61441U << 16 | 53410] =
00933 fix[10004LL<<32 | 61441U << 16 | 53503] =
00934 fix[10004LL<<32 | 61441U << 16 | 53411] =
00935 fix[10004LL<<32 | 61441U << 16 | 53412] =
00936 fix[10004LL<<32 | 61441U << 16 | 53112] =
00937 fix[10004LL<<32 | 61441U << 16 | 53513] =
00938 fix[10004LL<<32 | 61441U << 16 | 53618] =
00939 fix[10004LL<<32 | 61441U << 16 | 53619] =
00940 EITFixUp::kEFixForceISO8859_15;
00941
00942 fix[10005LL<<32 | 61441U << 16 | 50104] =
00943 fix[10005LL<<32 | 61441U << 16 | 50107] =
00944 fix[10005LL<<32 | 61441U << 16 | 50301] =
00945 fix[10005LL<<32 | 61441U << 16 | 50302] =
00946 fix[10005LL<<32 | 61441U << 16 | 50303] =
00947 fix[10005LL<<32 | 61441U << 16 | 50304] =
00948 fix[10005LL<<32 | 61441U << 16 | 50305] =
00949 fix[10005LL<<32 | 61441U << 16 | 50306] =
00950 fix[10005LL<<32 | 61441U << 16 | 50307] =
00951 fix[10005LL<<32 | 61441U << 16 | 53105] =
00952 fix[10005LL<<32 | 61441U << 16 | 53115] =
00953 fix[10005LL<<32 | 61441U << 16 | 53405] =
00954 fix[10005LL<<32 | 61441U << 16 | 53402] =
00955 fix[10005LL<<32 | 61441U << 16 | 53613] =
00956 fix[10005LL<<32 | 61441U << 16 | 53516] =
00957 fix[10005LL<<32 | 61441U << 16 | 53611] =
00958 fix[10005LL<<32 | 61441U << 16 | 53104] =
00959 EITFixUp::kEFixForceISO8859_15;
00960
00961 fix[10007LL<<32| 61441U << 16 | 53607] =
00962 fix[10007LL<<32| 61441U << 16 | 53608] =
00963 fix[10007LL<<32| 61441U << 16 | 53609] =
00964 fix[10007LL<<32| 61441U << 16 | 53628] =
00965 EITFixUp::kEFixForceISO8859_15;
00966
00967 fix[10007LL<<32| 61441U << 16 | 53601] =
00968 fix[10007LL<<32| 61441U << 16 | 53602] =
00969 fix[10007LL<<32| 61441U << 16 | 53604] =
00970 fix[10007LL<<32| 61441U << 16 | 53606] =
00971 EITFixUp::kFixRTL | EITFixUp::kFixCategory;
00972
00973 fix[ 10008LL<<32 | 61441U << 16 | 53002] =
00974 EITFixUp::kEFixForceISO8859_15;
00975
00976
00977 fix[ 1113LL << 32 | 1 << 16 | 12602] = EITFixUp::kEFixForceISO8859_15;
00978
00979
00980 fix[133 << 16] = EITFixUp::kEFixForceISO8859_15;
00981
00982
00983 fix[ 1022LL << 32 | 1 << 16 | 6901 ] =
00984 fix[ 1022LL << 32 | 1 << 16 | 6905 ] =
00985 fix[ 1022LL << 32 | 1 << 16 | 6911 ] =
00986 fix[ 1072LL << 32 | 1 << 16 | 8201 ] =
00987 fix[ 1070LL << 32 | 1 << 16 | 8004 ] =
00988 fix[ 1091LL << 32 | 1 << 16 | 31220 ] =
00989 fix[ 1094LL << 32 | 1 << 16 | 17027 ] =
00990 fix[ 1094LL << 32 | 1 << 16 | 17028 ] =
00991 fix[ 1100LL << 32 | 1 << 16 | 8710 ] =
00992 EITFixUp::kEFixForceISO8859_15;
00993 }
00994
00995 static int calc_eit_utc_offset(void)
00996 {
00997 QString config_offset = gCoreContext->GetSetting("EITTimeOffset", "Auto");
00998
00999 if (config_offset == "Auto")
01000 return calc_utc_offset();
01001
01002 if (config_offset == "None")
01003 return 0;
01004
01005 int sign = config_offset.left(1) == "-" ? -1 : +1;
01006 int hours = config_offset.mid(1,2).toInt();
01007 int minutes = config_offset.right(2).toInt();
01008 return sign * (hours * 60 * 60) + (minutes * 60);
01009 }