7 #include <QDomDocument>
36 const uchar *k = (
const uchar *)ba.data();
45 if ((g = (h & 0xf0000000)) != 0)
56 for (QDomNode dname = element.firstChild(); !dname.isNull();
57 dname = dname.nextSibling())
59 QDomText
t = dname.toText();
70 QString xmltvid = element.attribute(
"id",
"");
75 for (QDomNode child = element.firstChild(); !child.isNull();
76 child = child.nextSibling())
78 QDomElement info = child.toElement();
81 if (info.tagName() ==
"icon")
83 QString path = info.attribute(
"src",
"");
84 if (!path.isEmpty() && !path.contains(
"://"))
86 QString base = baseUrl.toString(QUrl::StripTrailingSlash);
87 chaninfo->
icon = base +
88 ((path.startsWith(
"/")) ? path : QString(
"/") + path);
90 else if (!path.isEmpty())
94 chaninfo->
icon = url.toString();
97 else if (info.tagName() ==
"display-name")
99 if (chaninfo->
name.isEmpty())
101 chaninfo->
name = info.text();
103 else if (chaninfo->
callsign.isEmpty())
107 else if (chaninfo->
channum.isEmpty())
109 chaninfo->
channum = info.text();
125 if (timestr.isEmpty())
127 LOG(VB_XMLTV, LOG_ERR,
"Found empty Date/Time in XMLTV data, ignoring");
131 QStringList split = timestr.split(
" ");
132 QString ts = split[0];
134 tmpDT.setTimeSpec(Qt::LocalTime);
137 if (ts.endsWith(
'Z'))
138 ts.truncate(ts.length()-1);
140 if (ts.length() == 14)
144 else if (ts.length() == 12)
148 else if (ts.length() == 8)
152 else if (ts.length() == 6)
156 else if (ts.length() == 4)
161 if (!tmpDT.isValid())
163 LOG(VB_GENERAL, LOG_ERR,
164 QString(
"Ignoring unknown timestamp format: %1")
169 if (split.size() > 1)
171 QString
tmp = split[1].trimmed();
176 if (tmp ==
"GMT" || tmp ==
"UTC")
178 else if (tmp ==
"BST")
182 QString isoDateString = QString(
"%1 %2").arg(tmpDT.toString(
Qt::ISODate))
189 static bool warned_once_on_implicit_utc =
false;
190 if (!warned_once_on_implicit_utc)
192 LOG(VB_XMLTV, LOG_ERR,
"No explicit time zone found, "
193 "guessing implicit UTC! Please consider enhancing "
194 "the guide source to provice explicit UTC or local "
196 warned_once_on_implicit_utc =
true;
201 dt.setTimeSpec(Qt::UTC);
208 for (QDomNode child = element.firstChild(); !child.isNull();
209 child = child.nextSibling())
211 QDomElement info = child.toElement();
219 for (QDomNode child = element.firstChild(); !child.isNull();
220 child = child.nextSibling())
222 QDomElement info = child.toElement();
225 if (info.tagName() ==
"quality")
230 else if (info.tagName() ==
"aspect")
241 for (QDomNode child = element.firstChild(); !child.isNull();
242 child = child.nextSibling())
244 QDomElement info = child.toElement();
247 if (info.tagName() ==
"stereo")
273 QString uniqueid, season, episode;
274 int dd_progid_done = 0;
277 QString text = element.attribute(
"start",
"");
281 text = element.attribute(
"stop",
"");
283 pginfo->
endts = text;
285 text = element.attribute(
"channel",
"");
286 QStringList split = text.split(
" ");
290 text = element.attribute(
"clumpidx",
"");
293 split = text.split(
'/');
298 for (QDomNode child = element.firstChild(); !child.isNull();
299 child = child.nextSibling())
301 QDomElement info = child.toElement();
304 if (info.tagName() ==
"title")
306 if (info.attribute(
"lang") ==
"ja_JP")
310 else if (info.attribute(
"lang") ==
"ja_JP@kana")
314 else if (pginfo->
title.isEmpty())
319 else if (info.tagName() ==
"sub-title" &&
324 else if (info.tagName() ==
"desc" && pginfo->
description.isEmpty())
328 else if (info.tagName() ==
"category")
337 else if (pginfo->
category.isEmpty())
342 if (cat == QObject::tr(
"movie") || cat == QObject::tr(
"film"))
348 else if (info.tagName() ==
"date" && !pginfo->
airdate)
352 pginfo->
airdate = date.left(4).toUInt();
354 else if (info.tagName() ==
"star-rating" && pginfo->
stars.isEmpty())
356 QDomNodeList values = info.elementsByTagName(
"value");
358 QString stars, num, den;
370 item = values.item(0).toElement();
374 num = stars.section(
'/', 0, 0);
375 den = stars.section(
'/', 1, 1);
376 if (0.0 < den.toFloat())
377 rating = num.toFloat()/den.toFloat();
380 pginfo->
stars.setNum(rating);
382 else if (info.tagName() ==
"rating")
386 QDomNodeList values = info.elementsByTagName(
"value");
387 QDomElement item = values.item(0).toElement();
391 rating.
system = info.attribute(
"system",
"");
393 pginfo->
ratings.append(rating);
395 else if (info.tagName() ==
"previously-shown")
399 QString prevdate = info.attribute(
"start");
400 if (!prevdate.isEmpty())
407 else if (info.tagName() ==
"credits")
411 else if (info.tagName() ==
"subtitles")
413 if (info.attribute(
"type") ==
"teletext")
415 else if (info.attribute(
"type") ==
"onscreen")
417 else if (info.attribute(
"type") ==
"deaf-signed")
420 else if (info.tagName() ==
"audio")
424 else if (info.tagName() ==
"video")
428 else if (info.tagName() ==
"episode-num")
430 if (info.attribute(
"system") ==
"dd_progid")
434 int idx = episodenum.indexOf(
'.');
436 episodenum.remove(idx, 1);
440 else if (info.attribute(
"system") ==
"xmltv_ns")
444 episode = episodenum.section(
'.',1,1);
445 episode = episode.section(
'/',0,0).trimmed();
446 season = episodenum.section(
'.',0,0).trimmed();
447 QString part(episodenum.section(
'.',2,2));
448 QString partnumber(part.section(
'/',0,0).trimmed());
449 QString parttotal(part.section(
'/',1,1).trimmed());
453 if (!episode.isEmpty())
455 tmp = episode.toInt() + 1;
456 episode = QString::number(tmp);
460 if (!season.isEmpty())
462 tmp = season.toInt() + 1;
463 season = QString::number(tmp);
468 if (!partnumber.isEmpty())
471 partno = partnumber.toUInt(&ok) + 1;
472 partno = (ok) ? partno : 0;
475 if (!parttotal.isEmpty() && partno > 0)
478 uint partto = parttotal.toUInt(&ok);
479 if (ok && partnumber <= parttotal)
486 else if (info.attribute(
"system") ==
"onscreen" &&
515 if (!uniqueid.isEmpty())
516 programid.append(uniqueid);
519 QString seriesid = QString::number(
ELFHash(pginfo->
title.toUtf8()));
521 programid.append(seriesid);
523 if (!episode.isEmpty() && !season.isEmpty())
529 int season_int = season.toInt();
539 programid.append(episode);
540 programid.append(QString::number(season_int, 36));
543 programid += QString::number(pginfo->
partnumber);
544 programid += QString::number(pginfo->
parttotal);
556 if (dd_progid_done == 0)
564 QMap<QString, QList<ProgInfo> > *proglist)
569 if (!
dash_open(f, filename, QIODevice::ReadOnly))
571 LOG(VB_GENERAL, LOG_ERR,
572 QString(
"Error unable to open '%1' for reading.") .arg(filename));
576 QString errorMsg =
"unknown";
580 if (!doc.setContent(&f, &errorMsg, &errorLine, &errorColumn))
582 LOG(VB_GENERAL, LOG_ERR, QString(
"Error in %1:%2: %3")
583 .arg(errorLine).arg(errorColumn).arg(errorMsg));
591 QDomElement docElem = doc.documentElement();
593 QUrl baseUrl(docElem.attribute(
"source-data-url",
""));
596 QString aggregatedTitle;
597 QString aggregatedDesc;
599 QDomNode
n = docElem.firstChild();
602 QDomElement e = n.toElement();
605 if (e.tagName() ==
"channel")
608 if (!chinfo->
xmltvid.isEmpty())
609 chanlist->push_back(*chinfo);
612 else if (e.tagName() ==
"programme")
618 LOG(VB_GENERAL, LOG_WARNING, QString(
"Invalid programme (%1), "
619 "identical start and end "
621 .arg(pginfo->
title));
626 (*proglist)[pginfo->
channel].push_back(*pginfo);
632 aggregatedTitle.clear();
633 aggregatedDesc.clear();
636 if (!pginfo->
title.isEmpty())
638 if (!aggregatedTitle.isEmpty())
639 aggregatedTitle.append(
" | ");
640 aggregatedTitle.append(pginfo->
title);
645 if (!aggregatedDesc.isEmpty())
646 aggregatedDesc.append(
" | ");
652 pginfo->
title = aggregatedTitle;
654 (*proglist)[pginfo->
channel].push_back(*pginfo);