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