16 #define LOC QString("ProgramData: ")
21 "actor",
"director",
"producer",
"executive_producer",
22 "writer",
"guest_star",
"host",
"adapter",
23 "presenter",
"commentator",
"guest",
28 return str.isNull() ?
"" : str;
38 role(_role),
name(_name)
44 role(kUnknown),
name(_name)
48 for (
uint i = 0; i <
sizeof(
roles) /
sizeof(
char *); i++)
50 if (_role == QString(
roles[i]))
65 const QDateTime &starttime)
const
79 "WHERE name = :NAME");
84 else if (query.
next())
85 return query.
value(0).toUInt();
93 "INSERT IGNORE INTO people (name) "
105 const QDateTime &starttime)
const
111 "REPLACE INTO credits "
112 " ( person, chanid, starttime, role) "
113 "VALUES (:PERSON, :CHANID, :STARTTIME, :ROLE) ");
116 query.
bindValue(
":STARTTIME", starttime);
223 if (match >= match_threshold)
225 LOG(VB_EIT, LOG_DEBUG,
226 QString(
"EIT: accept match[%1]: %2 '%3' vs. '%4'")
227 .arg(i).arg(match).arg(
title).arg(programs[i].
title));
228 return UpdateDB(query, chanid, programs, i);
234 LOG(VB_EIT, LOG_DEBUG,
235 QString(
"EIT: reject match[%1]: %2 '%3' vs. '%4'")
236 .arg(i).arg(match).arg(
title).arg(programs[i].
title));
238 return UpdateDB(query, chanid, programs, -1);
247 "SELECT title, subtitle, description, "
248 " category, category_type, "
249 " starttime, endtime, "
250 " subtitletypes+0,audioprop+0, videoprop+0, "
251 " seriesid, programid, "
252 " partnumber, parttotal, "
253 " syndicatedepisodenumber, "
254 " airdate, originalairdate, "
255 " previouslyshown,listingsource, "
258 "WHERE chanid = :CHANID AND "
260 " ( ( starttime >= :STIME1 AND starttime < :ETIME1 ) OR "
261 " ( endtime > :STIME2 AND endtime <= :ETIME2 ) )");
280 query.
value(0).toString(),
281 query.
value(1).toString(),
282 query.
value(2).toString(),
283 query.
value(3).toString(),
287 query.
value(7).toUInt(),
288 query.
value(8).toUInt(),
289 query.
value(9).toUInt(),
290 query.
value(19).toDouble(),
291 query.
value(10).toString(),
292 query.
value(11).toString(),
293 query.
value(18).toUInt());
296 prog.parttotal = query.
value(13).toUInt();
297 prog.syndicatedepisodenumber = query.
value(14).toString();
298 prog.airdate = query.
value(15).toUInt();
299 prog.originalairdate = query.
value(16).toDate();
300 prog.previouslyshown = query.
value(17).toBool();
303 programs.push_back(prog);
311 static int score_words(
const QStringList &al,
const QStringList &bl)
313 QStringList::const_iterator ait = al.begin();
314 QStringList::const_iterator bit = bl.begin();
316 for (; (ait != al.end()) && (bit != bl.end()); ++ait)
318 QStringList::const_iterator bit2 = bit;
321 for (; bit2 != bl.end(); ++bit2)
325 bscore = max(1000, 2000 - (dist * 500));
327 if (ait->length() < 5)
328 bscore /= 5 - ait->length();
333 if (bscore && dist < 3)
335 for (
int i = 0; (i < dist) && bit != bl.end(); i++)
341 return score / al.size();
346 if (a.isEmpty() || b.isEmpty())
351 QString A = a.simplified().toUpper();
352 QString B = b.simplified().toUpper();
357 al = A.split(
" ", QString::SkipEmptyParts);
361 bl = B.split(
" ", QString::SkipEmptyParts);
368 return min(900, score);
374 int match_val = INT_MIN;
378 for (
uint i = 0; i < programs.size(); i++)
381 int duration_loop = programs[i].starttime.secsTo(programs[i].
endtime);
383 mv -= abs(
starttime.secsTo(programs[i].starttime));
384 mv -= abs(endtime.secsTo(programs[i].endtime));
385 mv -= abs(duration - duration_loop);
393 overlap = programs[i].starttime.secsTo(endtime);
394 else if (starttime > programs[i].starttime)
395 overlap = starttime.secsTo(programs[i].endtime);
398 if (endtime <= programs[i].endtime)
399 overlap = starttime.secsTo(endtime);
401 overlap = starttime.secsTo(programs[i].endtime);
412 int min_dur = max(2, min(duration, duration_loop));
413 overlap = min(overlap, min_dur/2);
419 LOG(VB_GENERAL, LOG_ERR,
420 QString(
"Unexpected result: shows don't "
421 "overlap\n\t%1: %2 - %3\n\t%4: %5 - %6")
422 .arg(title.left(30), 30)
425 .arg(programs[i].title.left(30), 30)
433 LOG(VB_EIT, LOG_DEBUG,
434 QString(
"GM : %1 new best match %2 with score %3")
436 .arg(programs[i].title.left(25)).arg(mv));
446 MSqlQuery &q,
uint chanid,
const vector<DBEvent> &
p,
int match)
const
450 for (
uint i = 0; i < p.size(); i++)
452 if (i != (
uint)match)
461 if ((match < 0) || ((
uint)match >= p.size()))
465 return UpdateDB(q, chanid, p[match]);
471 QString ltitle =
title;
480 if (match.
title.length() >= ltitle.length())
481 ltitle = match.
title;
483 if (match.
subtitle.length() >= lsubtitle.length())
489 if (lcategory.isEmpty() && !match.
category.isEmpty())
498 if (lprogramId.isEmpty() && !match.
programId.isEmpty())
501 if (lseriesId.isEmpty() && !match.
seriesId.isEmpty())
524 if (lsyndicatedepisodenumber.isEmpty() &&
530 "SET title = :TITLE, subtitle = :SUBTITLE, "
531 " description = :DESC, "
532 " category = :CATEGORY, category_type = :CATTYPE, "
533 " starttime = :STARTTIME, endtime = :ENDTIME, "
534 " closecaptioned = :CC, subtitled = :HASSUBTITLES, "
535 " stereo = :STEREO, hdtv = :HDTV, "
536 " subtitletypes = :SUBTYPE, "
537 " audioprop = :AUDIOPROP, videoprop = :VIDEOPROP, "
538 " partnumber = :PARTNO, parttotal = :PARTTOTAL, "
539 " syndicatedepisodenumber = :SYNDICATENO, "
540 " airdate = :AIRDATE, originalairdate=:ORIGAIRDATE, "
541 " listingsource = :LSOURCE, "
542 " seriesid = :SERIESID, programid = :PROGRAMID, "
543 " previouslyshown = :PREVSHOWN "
544 "WHERE chanid = :CHANID AND "
545 " starttime = :OLDSTART ");
564 query.
bindValue(
":PARTTOTAL", lparttotal);
566 query.
bindValue(
":AIRDATE", lairdate?QString::number(lairdate):
"0000");
567 query.
bindValue(
":ORIGAIRDATE", loriginalairdate);
568 query.
bindValue(
":LSOURCE", llistingsource);
571 query.
bindValue(
":PREVSHOWN", lpreviouslyshown);
585 QList<EventRating>::const_iterator j =
ratings.begin();
586 for (; j !=
ratings.end(); ++j)
589 "INSERT INTO programrating "
590 " ( chanid, starttime, system, rating) "
591 "VALUES (:CHANID, :START, :SYS, :RATING)");
607 "DELETE from program "
608 "WHERE chanid = :CHANID AND "
609 " starttime = :STARTTIME");
621 "DELETE from credits "
622 "WHERE chanid = :CHANID AND "
623 " starttime = :STARTTIME");
638 const QDateTime &new_st,
const QDateTime &new_end)
642 "SET starttime = :NEWSTART, "
643 " endtime = :NEWEND "
644 "WHERE chanid = :CHANID AND "
645 " starttime = :OLDSTART");
660 "SET starttime = :NEWSTART "
661 "WHERE chanid = :CHANID AND "
662 " starttime = :OLDSTART");
704 "REPLACE INTO program ("
705 " chanid, title, subtitle, description, "
706 " category, category_type, "
707 " starttime, endtime, "
708 " closecaptioned, stereo, hdtv, subtitled, "
709 " subtitletypes, audioprop, videoprop, "
710 " stars, partnumber, parttotal, "
711 " syndicatedepisodenumber, "
712 " airdate, originalairdate,listingsource, "
713 " seriesid, programid, previouslyshown ) "
715 " :CHANID, :TITLE, :SUBTITLE, :DESCRIPTION, "
716 " :CATEGORY, :CATTYPE, "
717 " :STARTTIME, :ENDTIME, "
718 " :CC, :STEREO, :HDTV, :HASSUBTITLES, "
719 " :SUBTYPES, :AUDIOPROP, :VIDEOPROP, "
720 " :STARS, :PARTNUMBER, :PARTTOTAL, "
722 " :AIRDATE, :ORIGAIRDATE, :LSOURCE, "
723 " :SERIESID, :PROGRAMID, :PREVSHOWN) ");
820 LOG(VB_XMLTV, LOG_INFO,
821 QString(
"Inserting new program : %1 - %2 %3 %4")
828 "REPLACE INTO program ("
829 " chanid, title, subtitle, description, "
830 " category, category_type, "
831 " starttime, endtime, "
832 " closecaptioned, stereo, hdtv, subtitled, "
833 " subtitletypes, audioprop, videoprop, "
834 " partnumber, parttotal, "
835 " syndicatedepisodenumber, "
836 " airdate, originalairdate,listingsource, "
837 " seriesid, programid, previouslyshown, "
838 " stars, showtype, title_pronounce, colorcode ) "
841 " :CHANID, :TITLE, :SUBTITLE, :DESCRIPTION, "
842 " :CATEGORY, :CATTYPE, "
843 " :STARTTIME, :ENDTIME, "
844 " :CC, :STEREO, :HDTV, :HASSUBTITLES, "
845 " :SUBTYPES, :AUDIOPROP, :VIDEOPROP, "
846 " :PARTNUMBER, :PARTTOTAL, "
848 " :AIRDATE, :ORIGAIRDATE, :LSOURCE, "
849 " :SERIESID, :PROGRAMID, :PREVSHOWN, "
850 " :STARS, :SHOWTYPE, :TITLEPRON, :COLORCODE)");
893 QList<EventRating>::const_iterator j =
ratings.begin();
894 for (; j !=
ratings.end(); ++j)
897 "INSERT INTO programrating "
898 " ( chanid, starttime, system, rating) "
899 "VALUES (:CHANID, :START, :SYS, :RATING)");
919 uint chanid,
const QDateTime &from,
const QDateTime &to,
920 bool use_channel_time_offset)
923 if (use_channel_time_offset)
926 QDateTime newFrom = from.addSecs(secs);
927 QDateTime newTo = to.addSecs(secs);
930 query.
prepare(
"DELETE FROM program "
931 "WHERE starttime >= :FROM AND starttime < :TO "
932 "AND chanid = :CHANID ;");
936 bool ok = query.
exec();
938 query.
prepare(
"DELETE FROM programrating "
939 "WHERE starttime >= :FROM AND starttime < :TO "
940 "AND chanid = :CHANID ;");
946 query.
prepare(
"DELETE FROM credits "
947 "WHERE starttime >= :FROM AND starttime < :TO "
948 "AND chanid = :CHANID ;");
954 query.
prepare(
"DELETE FROM programgenres "
955 "WHERE starttime >= :FROM AND starttime < :TO "
956 "AND chanid = :CHANID ;");
966 uint sourceid,
const QDateTime &from,
const QDateTime &to,
967 bool use_channel_time_offset)
972 for (
uint i = 0; i < chanids.size(); i++)
987 QList<ProgInfo*>::iterator it = fixlist.begin();
990 QList<ProgInfo*>::iterator cur = it;
994 if ((*cur)->endts.isEmpty() || (*cur)->startts > (*cur)->endts)
996 if (it != fixlist.end())
998 (*cur)->endts = (*it)->startts;
999 (*cur)->endtime = (*it)->starttime;
1003 (*cur)->endtime = (*cur)->starttime;
1004 if ((*cur)->endtime < QDateTime(
1005 (*cur)->endtime.date(), QTime(6, 0), Qt::UTC))
1007 (*cur)->endtime = QDateTime(
1008 (*cur)->endtime.date(), QTime(6, 0), Qt::UTC);
1012 (*cur)->endtime = QDateTime(
1013 (*cur)->endtime.date().addDays(1),
1014 QTime(0, 0), Qt::UTC);
1022 if (it == fixlist.end())
1026 if ((*cur)->HasTimeConflict(**it))
1028 QList<ProgInfo*>::iterator tokeep, todelete;
1030 if ((*cur)->endtime <= (*cur)->starttime)
1031 tokeep = it, todelete = cur;
1032 else if ((*it)->endtime <= (*it)->starttime)
1033 tokeep = cur, todelete = it;
1034 else if (!(*cur)->subtitle.isEmpty() &&
1035 (*it)->subtitle.isEmpty())
1036 tokeep = cur, todelete = it;
1037 else if (!(*it)->subtitle.isEmpty() &&
1038 (*cur)->subtitle.isEmpty())
1039 tokeep = it, todelete = cur;
1040 else if (!(*cur)->description.isEmpty() &&
1041 (*it)->description.isEmpty())
1042 tokeep = cur, todelete = it;
1044 tokeep = it, todelete = cur;
1047 LOG(VB_XMLTV, LOG_INFO,
1048 QString(
"Removing conflicting program: %1 - %2 %3 %4")
1049 .arg((*todelete)->starttime.toString(
Qt::ISODate))
1051 .arg((*todelete)->channel)
1052 .arg((*todelete)->title));
1054 LOG(VB_XMLTV, LOG_INFO,
1055 QString(
"Conflicted with : %1 - %2 %3 %4")
1058 .arg((*tokeep)->channel)
1059 .arg((*tokeep)->title));
1061 bool step_back = todelete == it;
1062 it = fixlist.erase(todelete);
1070 uint sourceid, QMap<QString, QList<ProgInfo> > &proglist)
1072 uint unchanged = 0, updated = 0;
1076 QMap<QString, QList<ProgInfo> >::const_iterator mapiter;
1077 for (mapiter = proglist.begin(); mapiter != proglist.end(); ++mapiter)
1079 if (mapiter.key().isEmpty())
1085 "WHERE sourceid = :ID AND "
1086 " xmltvid = :XMLTVID");
1088 query.
bindValue(
":XMLTVID", mapiter.key());
1096 vector<uint> chanids;
1097 while (query.
next())
1098 chanids.push_back(query.
value(0).toUInt());
1100 if (chanids.empty())
1102 LOG(VB_GENERAL, LOG_NOTICE,
1103 QString(
"Unknown xmltv channel identifier: %1"
1104 " - Skipping channel.").arg(mapiter.key()));
1108 QList<ProgInfo> &list = proglist[mapiter.key()];
1109 QList<ProgInfo*> sortlist;
1110 QList<ProgInfo>::iterator it = list.begin();
1111 for (; it != list.end(); ++it)
1112 sortlist.push_back(&(*it));
1116 for (
uint i = 0; i < chanids.size(); ++i)
1122 LOG(VB_GENERAL, LOG_INFO,
1123 QString(
"Updated programs: %1 Unchanged programs: %2")
1124 .arg(updated) .arg(unchanged));
1129 const QList<ProgInfo*> &sortlist,
1133 QList<ProgInfo*>::const_iterator it = sortlist.begin();
1134 for (; it != sortlist.end(); ++it)
1145 updated += (*it)->InsertDB(query, chanid);
1152 QString chanid, starttime, endtime, querystr;
1155 querystr =
"SELECT chanid, starttime, endtime FROM program "
1156 "WHERE (DATE_FORMAT(endtime,'%H%i') = '0000') "
1157 "ORDER BY chanid, starttime;";
1159 if (!query1.exec(querystr))
1161 LOG(VB_GENERAL, LOG_ERR,
1162 QString(
"fix_end_times query failed: %1").arg(querystr));
1166 while (query1.next())
1168 starttime = query1.value(1).toString();
1169 chanid = query1.value(0).toString();
1170 endtime = query1.value(2).toString();
1172 querystr = QString(
"SELECT chanid, starttime, endtime FROM program "
1173 "WHERE starttime BETWEEN '%1 00:00:00'"
1174 "AND '%2 23:59:59' AND chanid = '%3' "
1175 "ORDER BY starttime LIMIT 1;")
1176 .arg(endtime.left(10))
1177 .arg(endtime.left(10))
1180 if (!query2.
exec(querystr))
1182 LOG(VB_GENERAL, LOG_ERR,
1183 QString(
"fix_end_times query failed: %1").arg(querystr));
1187 if (query2.
next() && (endtime != query2.
value(1).toString()))
1190 endtime = query2.
value(1).toString();
1191 querystr = QString(
"UPDATE program SET starttime = '%1', "
1192 "endtime = '%2' WHERE (chanid = '%3' AND "
1193 "starttime = '%4');")
1199 if (!query2.
exec(querystr))
1201 LOG(VB_GENERAL, LOG_ERR,
1202 QString(
"fix_end_times query failed: %1").arg(querystr));
1217 "WHERE chanid = :CHANID AND "
1218 " starttime = :START AND "
1219 " endtime = :END AND "
1220 " title = :TITLE AND "
1221 " subtitle = :SUBTITLE AND "
1222 " description = :DESC AND "
1223 " category = :CATEGORY AND "
1224 " category_type = :CATEGORY_TYPE AND "
1225 " airdate = :AIRDATE AND "
1226 " stars >= (:STARS1 - 0.001) AND "
1227 " stars <= (:STARS2 + 0.001) AND "
1228 " previouslyshown = :PREVIOUSLYSHOWN AND "
1229 " title_pronounce = :TITLE_PRONOUNCE AND "
1230 " audioprop = :AUDIOPROP AND "
1231 " videoprop = :VIDEOPROP AND "
1232 " subtitletypes = :SUBTYPES AND "
1233 " partnumber = :PARTNUMBER AND "
1234 " parttotal = :PARTTOTAL AND "
1235 " seriesid = :SERIESID AND "
1236 " showtype = :SHOWTYPE AND "
1237 " colorcode = :COLORCODE AND "
1238 " syndicatedepisodenumber = :SYNDICATEDEPISODENUMBER AND "
1239 " programid = :PROGRAMID");
1250 query.
bindValue(
":CATEGORY_TYPE", cattype);
1264 query.
bindValue(
":SYNDICATEDEPISODENUMBER",
1269 return query.
value(0).toUInt() > 0;
1277 if (VERBOSE_LEVEL_CHECK(VB_XMLTV, LOG_INFO))
1281 "SELECT title,starttime,endtime "
1283 "WHERE chanid = :CHANID AND "
1284 " starttime >= :START AND "
1285 " starttime < :END;");
1298 LOG(VB_XMLTV, LOG_INFO,
1299 QString(
"Removing existing program: %1 - %2 %3 %4")
1303 .arg(query.
value(0).toString()));
1304 }
while (query.
next());
1309 LOG(VB_XMLTV, LOG_ERR,
1310 QString(
"Program delete failed : %1 - %2 %3 %4")