MythTV  master
metadatacommon.cpp
Go to the documentation of this file.
1 #include <algorithm>
2 #include <utility>
3 
4 // Qt headers
5 #include <QCoreApplication>
6 #include <QLocale>
7 #include <QMetaType>
8 #include <QRegularExpression>
9 
11 #include "libmythbase/mythlocale.h"
15 #include "libmythbase/rssparse.h"
16 
17 #include "metadatacommon.h"
18 
19 static int x0 = qRegisterMetaType< RefCountHandler<MetadataLookup> >();
20 
21 // full constructor
24  LookupType subtype,
25  QVariant data,
26  LookupStep step,
27  bool automatic,
28  bool handleimages,
29  bool allowoverwrites,
30  bool allowgeneric,
31  bool preferdvdorder,
32  QString host,
33  QString filename,
34  const QString &title,
35  QString network,
36  QString status,
37  QStringList categories,
38  const float userrating,
39  uint ratingcount,
40  QString language,
41  QString subtitle,
42  QString tagline,
43  QString description,
44  uint season,
45  uint episode,
46  uint chanid,
47  QString channum,
48  QString chansign,
49  QString channame,
50  QString chanplaybackfilters,
51  QString recgroup,
52  QString playgroup,
53  QString seriesid,
54  QString programid,
55  QString storagegroup,
56  QDateTime startts,
57  QDateTime endts,
58  QDateTime recstartts,
59  QDateTime recendts,
60  uint programflags,
61  uint audioproperties,
62  uint videoproperties,
63  uint subtitletype,
64  QString certification,
65  QStringList countries,
66  const float popularity,
67  const uint budget,
68  const uint revenue,
69  QString album,
70  uint tracknum,
71  QString system,
72  const uint year,
73  const QDate releasedate,
74  QDateTime lastupdated,
75  std::chrono::minutes runtime,
76  std::chrono::seconds runtimesecs,
77  QString inetref,
78  QString collectionref,
79  QString tmsref,
80  QString imdb,
81  PeopleMap people,
82  QStringList studios,
83  QString homepage,
84  QString trailerURL,
85  ArtworkMap artwork,
86  DownloadMap downloads) :
87  ReferenceCounter("MetadataLookup"),
88 
89  m_type(type),
90  m_subtype(subtype),
91  m_data(std::move(data)),
92  m_step(step),
93  m_automatic(automatic),
94  m_handleImages(handleimages),
95  m_allowOverwrites(allowoverwrites),
96  m_allowGeneric(allowgeneric),
97  m_dvdOrder(preferdvdorder),
98  m_host(std::move(host)),
99  m_filename(std::move(filename)),
100  m_title(title),
101  m_network(std::move(network)),
102  m_status(std::move(status)),
103  m_categories(std::move(categories)),
104  m_userRating(userrating),
105  m_ratingCount(ratingcount),
106  m_language(std::move(language)),
107  m_subtitle(std::move(subtitle)),
108  m_tagline(std::move(tagline)),
109  m_description(std::move(description)),
110  m_season(season),
111  m_episode(episode),
112  m_chanId(chanid),
113  m_chanNum(std::move(channum)),
114  m_chanSign(std::move(chansign)),
115  m_chanName(std::move(channame)),
116  m_chanPlaybackFilters(std::move(chanplaybackfilters)),
117  m_recGroup(std::move(recgroup)),
118  m_playGroup(std::move(playgroup)),
119  m_seriesId(std::move(seriesid)),
120  m_programid(std::move(programid)),
121  m_storageGroup(std::move(storagegroup)),
122  m_startTs(std::move(startts)),
123  m_endTs(std::move(endts)),
124  m_recStartTs(std::move(recstartts)),
125  m_recEndTs(std::move(recendts)),
126  m_programFlags(programflags),
127  m_audioProperties(audioproperties),
128  m_videoProperties(videoproperties),
129  m_subtitleType(subtitletype),
130  m_certification(std::move(certification)),
131  m_countries(std::move(countries)),
132  m_popularity(popularity),
133  m_budget(budget),
134  m_revenue(revenue),
135  m_album(std::move(album)),
136  m_trackNum(tracknum),
137  m_system(std::move(system)),
138  m_year(year),
139  m_releaseDate(releasedate),
140  m_lastUpdated(std::move(lastupdated)),
141  m_runtime(runtime),
142  m_runtimeSecs(runtimesecs),
143  m_inetRef(std::move(inetref)),
144  m_collectionRef(std::move(collectionref)),
145  m_tmsRef(std::move(tmsref)),
146  m_imdb(std::move(imdb)),
147  m_people(std::move(people)),
148  m_studios(std::move(studios)),
149  m_homepage(std::move(homepage)),
150  m_trailerURL(std::move(trailerURL)),
151  m_artwork(std::move(artwork)),
152  m_downloads(std::move(downloads))
153 {
154  QString manRecSuffix = QString(" (%1)").arg(QObject::tr("Manual Record"));
155  m_baseTitle = title;
156  m_baseTitle.replace(manRecSuffix,"");
157 }
158 
159 // ProgramInfo-style constructor
162  LookupType subtype,
163  QVariant data,
164  LookupStep step,
165  bool automatic,
166  bool handleimages,
167  bool allowoverwrites,
168  bool allowgeneric,
169  bool preferdvdorder,
170  QString host,
171  QString filename,
172  const QString &title,
173  QStringList categories,
174  const float userrating,
175  QString subtitle,
176  QString description,
177  uint chanid,
178  QString channum,
179  QString chansign,
180  QString channame,
181  QString chanplaybackfilters,
182  QString recgroup,
183  QString playgroup,
184  QString seriesid,
185  QString programid,
186  QString storagegroup,
187  QDateTime startts,
188  QDateTime endts,
189  QDateTime recstartts,
190  QDateTime recendts,
191  uint programflags,
192  uint audioproperties,
193  uint videoproperties,
194  uint subtitletype,
195  const uint year,
196  const QDate releasedate,
197  QDateTime lastupdated,
198  std::chrono::minutes runtime,
199  std::chrono::seconds runtimesecs) :
200  ReferenceCounter("MetadataLookup"),
201 
202  m_type(type),
203  m_subtype(subtype),
204  m_data(std::move(data)),
205  m_step(step),
206  m_automatic(automatic),
207  m_handleImages(handleimages),
208  m_allowOverwrites(allowoverwrites),
209  m_allowGeneric(allowgeneric),
210  m_dvdOrder(preferdvdorder),
211  m_host(std::move(host)),
212  m_filename(std::move(filename)),
213  m_title(title),
214  m_categories(std::move(categories)),
215  m_userRating(userrating),
216  m_subtitle(std::move(subtitle)),
217  m_description(std::move(description)),
218  m_chanId(chanid),
219  m_chanNum(std::move(channum)),
220  m_chanSign(std::move(chansign)),
221  m_chanName(std::move(channame)),
222  m_chanPlaybackFilters(std::move(chanplaybackfilters)),
223  m_recGroup(std::move(recgroup)),
224  m_playGroup(std::move(playgroup)),
225  m_seriesId(std::move(seriesid)),
226  m_programid(std::move(programid)),
227  m_storageGroup(std::move(storagegroup)),
228  m_startTs(std::move(startts)),
229  m_endTs(std::move(endts)),
230  m_recStartTs(std::move(recstartts)),
231  m_recEndTs(std::move(recendts)),
232  m_programFlags(programflags),
233  m_audioProperties(audioproperties),
234  m_videoProperties(videoproperties),
235  m_subtitleType(subtitletype),
236  m_year(year),
237  m_releaseDate(releasedate),
238  m_lastUpdated(std::move(lastupdated)),
239  m_runtime(runtime),
240  m_runtimeSecs(runtimesecs)
241 {
242  QString manRecSuffix = QString(" (%1)").arg(QObject::tr("Manual Record"));
243  m_baseTitle = title;
244  m_baseTitle.replace(manRecSuffix,"");
245 }
246 
247 // XBMC NFO-style constructor
250  LookupType subtype,
251  QVariant data,
252  LookupStep step,
253  bool automatic,
254  bool handleimages,
255  bool allowoverwrites,
256  bool allowgeneric,
257  bool preferdvdorder,
258  QString host,
259  QString filename,
260  const QString &title,
261  QStringList categories,
262  const float userrating,
263  QString subtitle,
264  QString tagline,
265  QString description,
266  uint season,
267  uint episode,
268  QString certification,
269  const uint year,
270  const QDate releasedate,
271  std::chrono::minutes runtime,
272  std::chrono::seconds runtimesecs,
273  QString inetref,
274  PeopleMap people,
275  QString trailerURL,
276  ArtworkMap artwork,
277  DownloadMap downloads) :
278  ReferenceCounter("MetadataLookup"),
279 
280  m_type(type),
281  m_subtype(subtype),
282  m_data(std::move(data)),
283  m_step(step),
284  m_automatic(automatic),
285  m_handleImages(handleimages),
286  m_allowOverwrites(allowoverwrites),
287  m_allowGeneric(allowgeneric),
288  m_dvdOrder(preferdvdorder),
289  m_host(std::move(host)),
290  m_filename(std::move(filename)),
291  m_title(title),
292  m_categories(std::move(categories)),
293  m_userRating(userrating),
294  m_subtitle(std::move(subtitle)),
295  m_tagline(std::move(tagline)),
296  m_description(std::move(description)),
297  m_season(season),
298  m_episode(episode),
299  m_certification(std::move(certification)),
300  m_year(year),
301  m_releaseDate(releasedate),
302  m_runtime(runtime),
303  m_runtimeSecs(runtimesecs),
304  m_inetRef(std::move(inetref)),
305  m_people(std::move(people)),
306  m_trailerURL(std::move(trailerURL)),
307  m_artwork(std::move(artwork)),
308  m_downloads(std::move(downloads))
309 {
310  QString manRecSuffix = QString(" (%1)").arg(QObject::tr("Manual Record"));
311  m_baseTitle = title;
312  m_baseTitle.replace(manRecSuffix,"");
313 }
314 
315 QList<PersonInfo> MetadataLookup::GetPeople(PeopleType type) const
316 {
317  QList<PersonInfo> ret;
318  // QMultiMap::values() returns items in reverse order which we need to
319  // correct by iterating back over the list
320  // See http://qt-project.org/doc/qt-4.8/qmultimap.html#details
321  // Specifically "The items that share the same key are available from "
322  // "most recently to least recently inserted."
323  QListIterator<PersonInfo> it(m_people.values(type));
324  it.toBack();
325  while (it.hasPrevious())
326  ret.append(it.previous());
327 
328  return ret;
329 }
330 
332 {
333  ArtworkList ret;
334 
335  // QMultiMap::values() returns items in reverse order which we need to
336  // correct by iterating back over the list
337  // See http://qt-project.org/doc/qt-4.8/qmultimap.html#details
338  // Specifically "The items that share the same key are available from "
339  // "most recently to least recently inserted."
340  QListIterator<ArtworkInfo> it(m_artwork.values(type));
341  it.toBack();
342  while (it.hasPrevious())
343  ret.append(it.previous());
344 
345  return ret;
346 }
347 
348 void MetadataLookup::toMap(InfoMap &metadataMap)
349 {
350  metadataMap["filename"] = m_filename;
351  metadataMap["title"] = m_title;
352  metadataMap["network"] = m_network;
353  metadataMap["status"] = m_status;
354  metadataMap["category"] = m_categories.join(", ");
355  metadataMap["userrating"] = QString::number(m_userRating);
356  metadataMap["ratingcount"] = QString::number(m_ratingCount);
357  metadataMap["language"] = m_language;
358  metadataMap["subtitle"] = m_subtitle;
359  metadataMap["tagline"] = m_tagline;
360  metadataMap["description0"] = metadataMap["description"] = m_description;
361  metadataMap["season"] = QString::number(m_season);
362  metadataMap["episode"] = QString::number(m_episode);
363  metadataMap["chanid"] = QString::number(m_chanId);
364  metadataMap["channum"] = m_chanNum;
365  metadataMap["callsign"] = m_chanSign;
366  metadataMap["channame"] = m_chanName;
367  metadataMap["playbackfilters"] = m_chanPlaybackFilters;
368  metadataMap["recgroup"] = m_recGroup;
369  metadataMap["playgroup"] = m_playGroup;
370  metadataMap["seriesid"] = m_seriesId;
371  metadataMap["programid"] = m_programid;
372  metadataMap["storagegroup"] = m_storageGroup;
373  metadataMap["startts"] = MythDate::toString(m_startTs, MythDate::kDateFull);
374  metadataMap["endts"] = MythDate::toString(m_endTs, MythDate::kDateFull);
375  metadataMap["recstartts"] = MythDate::toString(m_recStartTs, MythDate::kDateFull);
376  metadataMap["recendts"] = MythDate::toString(m_recEndTs, MythDate::kDateFull);
377  metadataMap["certification"] = m_certification;
378  metadataMap["countries"] = m_countries.join(", ");
379  metadataMap["popularity"] = QString::number(m_popularity);
380  metadataMap["budget"] = QString::number(m_budget);
381  metadataMap["revenue"] = QString::number(m_revenue);
382  metadataMap["album"] = m_album;
383  metadataMap["tracknum"] = QString::number(m_trackNum);
384  metadataMap["system"] = m_system;
385  metadataMap["year"] = QString::number(m_year);
386 
387  metadataMap["releasedate"] = MythDate::toString(
389  metadataMap["lastupdated"] = MythDate::toString(m_lastUpdated, MythDate::kDateFull);
390 
391  metadataMap["runtime"] = QCoreApplication::translate("(Common)",
392  "%n minute(s)",
393  "",
394  m_runtime.count());
395 
396 
397  metadataMap["runtimesecs"] = QCoreApplication::translate("(Common)",
398  "%n second(s)",
399  "",
400  m_runtimeSecs.count());
401  metadataMap["inetref"] = m_inetRef;
402  metadataMap["collectionref"] = m_collectionRef;
403  metadataMap["tmsref"] = m_tmsRef;
404  metadataMap["imdb"] = m_imdb;
405  metadataMap["studios"] = m_studios.join(", ");
406  metadataMap["homepage"] = m_homepage;
407  metadataMap["trailer"] = m_trailerURL;
408 }
409 
411 {
412  auto runtimesecs =
413  std::chrono::seconds(pginfo->GetRecordingStartTime()
414  .secsTo(pginfo->GetRecordingEndTime()));
415  auto runtime = duration_cast<std::chrono::minutes>(runtimesecs);
416 
418  QVariant::fromValue(pginfo), kLookupData, false, false, false, false, false,
419  pginfo->GetHostname(),pginfo->GetBasename(),pginfo->GetTitle(),
420  QStringList() << pginfo->GetCategory(), pginfo->GetStars() * 10,
421  pginfo->GetSubtitle(), pginfo->GetDescription(), pginfo->GetChanID(),
422  pginfo->GetChanNum(), pginfo->GetChannelSchedulingID(),
423  pginfo->GetChannelName(), pginfo->GetChannelPlaybackFilters(),
424  pginfo->GetRecordingGroup(), pginfo->GetPlaybackGroup(),
425  pginfo->GetSeriesID(), pginfo->GetProgramID(), pginfo->GetStorageGroup(),
426  pginfo->GetScheduledStartTime(), pginfo->GetScheduledEndTime(),
427  pginfo->GetRecordingStartTime(), pginfo->GetRecordingEndTime(),
428  pginfo->GetProgramFlags(), pginfo->GetAudioProperties(),
429  pginfo->GetVideoProperties(), pginfo->GetSubtitleType(),
430  pginfo->GetYearOfInitialRelease(), pginfo->GetOriginalAirDate(),
431  pginfo->GetLastModifiedTime(), runtime, runtimesecs);
432 
433  ret->SetSeason(pginfo->GetSeason());
434  ret->SetEpisode(pginfo->GetEpisode());
435  ret->SetInetref(pginfo->GetInetRef());
436 
437  return ret;
438 }
439 
441 {
442  QDomDocument doc("MythMetadataXML");
443 
444  QDomElement root = doc.createElement("metadata");
445  doc.appendChild(root);
446 
447  for (const auto & item : std::as_const(list))
448  CreateMetadataXMLItem(item, root, doc);
449 
450  return doc;
451 }
452 
453 QDomDocument CreateMetadataXML(MetadataLookup *lookup)
454 {
455  QDomDocument doc("MythMetadataXML");
456 
457  QDomElement root = doc.createElement("metadata");
458  doc.appendChild(root);
459 
460  CreateMetadataXMLItem(lookup, root, doc);
461 
462  return doc;
463 }
464 
465 QDomDocument CreateMetadataXML(ProgramInfo *pginfo)
466 {
467  QDomDocument doc("MythMetadataXML");
468 
469  MetadataLookup *lookup = LookupFromProgramInfo(pginfo);
470  if (lookup)
471  {
472  doc = CreateMetadataXML(lookup);
473  lookup->DecrRef();
474  }
475  lookup = nullptr;
476 
477  return doc;
478 }
479 
481  QDomElement placetoadd,
482  QDomDocument docroot)
483 {
484  if (!lookup)
485  return;
486 
487  QDomElement item = docroot.createElement("item");
488  placetoadd.appendChild(item);
489  QString RFC822("ddd, d MMMM yyyy hh:mm:ss");
490 
491  // Language
492  if (!lookup->GetLanguage().isEmpty())
493  {
494  QDomElement language = docroot.createElement("language");
495  item.appendChild(language);
496  language.appendChild(docroot.createTextNode(lookup->GetLanguage()));
497  }
498  // Title
499  if (!lookup->GetTitle().isEmpty())
500  {
501  QDomElement title = docroot.createElement("title");
502  item.appendChild(title);
503  title.appendChild(docroot.createTextNode(lookup->GetTitle()));
504  }
505  // Subtitle
506  if (!lookup->GetSubtitle().isEmpty())
507  {
508  QDomElement subtitle = docroot.createElement("subtitle");
509  item.appendChild(subtitle);
510  subtitle.appendChild(docroot.createTextNode(lookup->GetSubtitle()));
511  }
512  // Network
513  if (!lookup->GetNetwork().isEmpty())
514  {
515  QDomElement network = docroot.createElement("network");
516  item.appendChild(network);
517  network.appendChild(docroot.createTextNode(lookup->GetNetwork()));
518  }
519  // Status
520  if (!lookup->GetStatus().isEmpty())
521  {
522  QDomElement status = docroot.createElement("status");
523  item.appendChild(status);
524  status.appendChild(docroot.createTextNode(lookup->GetStatus()));
525  }
526  // Season and Episode
527  if (lookup->GetSeason() > 0 || lookup->GetEpisode() > 0)
528  {
529  QDomElement season = docroot.createElement("season");
530  item.appendChild(season);
531  season.appendChild(docroot.createTextNode(
532  QString::number(lookup->GetSeason())));
533 
534  QDomElement episode = docroot.createElement("episode");
535  item.appendChild(episode);
536  episode.appendChild(docroot.createTextNode(
537  QString::number(lookup->GetEpisode())));
538  }
539  // Tagline
540  if (!lookup->GetTagline().isEmpty())
541  {
542  QDomElement tagline = docroot.createElement("tagline");
543  item.appendChild(tagline);
544  tagline.appendChild(docroot.createTextNode(lookup->GetTagline()));
545  }
546  // Plot
547  if (!lookup->GetDescription().isEmpty())
548  {
549  QDomElement desc = docroot.createElement("description");
550  item.appendChild(desc);
551  desc.appendChild(docroot.createTextNode(lookup->GetDescription()));
552  }
553  // Album Name
554  if (!lookup->GetAlbumTitle().isEmpty())
555  {
556  QDomElement albumname = docroot.createElement("albumname");
557  item.appendChild(albumname);
558  albumname.appendChild(docroot.createTextNode(lookup->GetAlbumTitle()));
559  }
560  // Inetref
561  if (!lookup->GetInetref().isEmpty())
562  {
563  QDomElement inetref = docroot.createElement("inetref");
564  item.appendChild(inetref);
565  inetref.appendChild(docroot.createTextNode(lookup->GetInetref()));
566  }
567  // Collectionref
568  if (!lookup->GetCollectionref().isEmpty())
569  {
570  QDomElement collectionref = docroot.createElement("collectionref");
571  item.appendChild(collectionref);
572  collectionref.appendChild(docroot.createTextNode(lookup->GetCollectionref()));
573  }
574  // TMSref/SeriesID
575  if (!lookup->GetTMSref().isEmpty())
576  {
577  QDomElement tmsref = docroot.createElement("tmsref");
578  item.appendChild(tmsref);
579  tmsref.appendChild(docroot.createTextNode(lookup->GetTMSref()));
580  }
581  // IMDB
582  if (!lookup->GetIMDB().isEmpty())
583  {
584  QDomElement imdb = docroot.createElement("imdb");
585  item.appendChild(imdb);
586  imdb.appendChild(docroot.createTextNode(lookup->GetIMDB()));
587  }
588  // Home Page
589  if (!lookup->GetHomepage().isEmpty())
590  {
591  QDomElement homepage = docroot.createElement("homepage");
592  item.appendChild(homepage);
593  homepage.appendChild(docroot.createTextNode(lookup->GetHomepage()));
594  }
595  // Trailer
596  if (!lookup->GetTrailerURL().isEmpty())
597  {
598  QDomElement trailer = docroot.createElement("trailer");
599  item.appendChild(trailer);
600  trailer.appendChild(docroot.createTextNode(lookup->GetTrailerURL()));
601  }
602  // Chan ID
603  if (lookup->GetChanId() > 0)
604  {
605  QDomElement chanid = docroot.createElement("chanid");
606  item.appendChild(chanid);
607  chanid.appendChild(docroot.createTextNode(
608  QString::number(lookup->GetChanId())));
609  }
610  // Channel Number
611  if (!lookup->GetChanNum().isEmpty())
612  {
613  QDomElement channum = docroot.createElement("channum");
614  item.appendChild(channum);
615  channum.appendChild(docroot.createTextNode(lookup->GetChanNum()));
616  }
617  // Callsign
618  if (!lookup->GetChanSign().isEmpty())
619  {
620  QDomElement callsign = docroot.createElement("chansign");
621  item.appendChild(callsign);
622  callsign.appendChild(docroot.createTextNode(lookup->GetChanSign()));
623  }
624  // Channel Name
625  if (!lookup->GetChanName().isEmpty())
626  {
627  QDomElement channame = docroot.createElement("channame");
628  item.appendChild(channame);
629  channame.appendChild(docroot.createTextNode(lookup->GetChanName()));
630  }
631  // Playback Filters
632  if (!lookup->GetChanPlaybackFilters().isEmpty())
633  {
634  QDomElement filters = docroot.createElement("filters");
635  item.appendChild(filters);
636  filters.appendChild(docroot.createTextNode(
637  lookup->GetChanPlaybackFilters()));
638  }
639  // Recording Group
640  if (!lookup->GetRecGroup().isEmpty())
641  {
642  QDomElement recgroup = docroot.createElement("recgroup");
643  item.appendChild(recgroup);
644  recgroup.appendChild(docroot.createTextNode(lookup->GetRecGroup()));
645  }
646  // Playback Group
647  if (!lookup->GetPlayGroup().isEmpty())
648  {
649  QDomElement playgroup = docroot.createElement("playgroup");
650  item.appendChild(playgroup);
651  playgroup.appendChild(docroot.createTextNode(lookup->GetPlayGroup()));
652  }
653  // SeriesID
654  if (!lookup->GetSeriesId().isEmpty())
655  {
656  QDomElement seriesid = docroot.createElement("seriesid");
657  item.appendChild(seriesid);
658  seriesid.appendChild(docroot.createTextNode(lookup->GetSeriesId()));
659  }
660  // ProgramID
661  if (!lookup->GetProgramId().isEmpty())
662  {
663  QDomElement programid = docroot.createElement("programid");
664  item.appendChild(programid);
665  programid.appendChild(docroot.createTextNode(lookup->GetProgramId()));
666  }
667  // Storage Group
668  if (!lookup->GetStorageGroup().isEmpty())
669  {
670  QDomElement sgroup = docroot.createElement("storagegroup");
671  item.appendChild(sgroup);
672  sgroup.appendChild(docroot.createTextNode(lookup->GetStorageGroup()));
673  }
674  // Start TS
675  if (!lookup->GetStartTS().isNull())
676  {
677  QDomElement startts = docroot.createElement("startts");
678  item.appendChild(startts);
679  startts.appendChild(docroot.createTextNode(
680  lookup->GetStartTS().toString(RFC822)));
681  }
682  // End TS
683  if (!lookup->GetEndTS().isNull())
684  {
685  QDomElement endts = docroot.createElement("endts");
686  item.appendChild(endts);
687  endts.appendChild(docroot.createTextNode(
688  lookup->GetEndTS().toString(RFC822)));
689  }
690  // Rec Start TS
691  if (!lookup->GetRecStartTS().isNull())
692  {
693  QDomElement recstartts = docroot.createElement("recstartts");
694  item.appendChild(recstartts);
695  recstartts.appendChild(docroot.createTextNode(
696  lookup->GetRecStartTS().toString(RFC822)));
697  }
698  // Rec End TS
699  if (!lookup->GetRecEndTS().isNull())
700  {
701  QDomElement recendts = docroot.createElement("recendts");
702  item.appendChild(recendts);
703  recendts.appendChild(docroot.createTextNode(
704  lookup->GetRecEndTS().toString(RFC822)));
705  }
706  // Program Flags
707  if (lookup->GetProgramFlags() > 0)
708  {
709  QDomElement progflags = docroot.createElement("programflags");
710  item.appendChild(progflags);
711  progflags.appendChild(docroot.createTextNode(
712  QString::number(lookup->GetProgramFlags())));
713  }
714  // Audio Properties
715  if (lookup->GetAudioProperties() > 0)
716  {
717  QDomElement audioprops = docroot.createElement("audioproperties");
718  item.appendChild(audioprops);
719  audioprops.appendChild(docroot.createTextNode(
720  QString::number(lookup->GetAudioProperties())));
721  }
722  // Video Properties
723  if (lookup->GetVideoProperties() > 0)
724  {
725  QDomElement videoprops = docroot.createElement("videoproperties");
726  item.appendChild(videoprops);
727  videoprops.appendChild(docroot.createTextNode(
728  QString::number(lookup->GetVideoProperties())));
729  }
730  // Subtitle Type
731  if (lookup->GetSubtitleType() > 0)
732  {
733  QDomElement subprops = docroot.createElement("subtitletype");
734  item.appendChild(subprops);
735  subprops.appendChild(docroot.createTextNode(
736  QString::number(lookup->GetSubtitleType())));
737  }
738  // Release Date
739  if (!lookup->GetReleaseDate().isNull())
740  {
741  QDomElement releasedate = docroot.createElement("releasedate");
742  item.appendChild(releasedate);
743  releasedate.appendChild(docroot.createTextNode(
744  lookup->GetReleaseDate().toString("yyyy-MM-dd")));
745  }
746  // Last Updated
747  if (!lookup->GetLastUpdated().isNull())
748  {
749  QDomElement lastupdated = docroot.createElement("lastupdated");
750  item.appendChild(lastupdated);
751  lastupdated.appendChild(docroot.createTextNode(
752  lookup->GetLastUpdated().toString(RFC822)));
753  }
754  // User Rating
755  if (lookup->GetUserRating() > 0)
756  {
757  QDomElement userrating = docroot.createElement("userrating");
758  item.appendChild(userrating);
759  userrating.appendChild(docroot.createTextNode(QString::number(
760  lookup->GetUserRating())));
761  }
762  // Rating Count
763  if (lookup->GetRatingCount() > 0)
764  {
765  QDomElement ratingcount = docroot.createElement("ratingcount");
766  item.appendChild(ratingcount);
767  ratingcount.appendChild(docroot.createTextNode(QString::number(
768  lookup->GetRatingCount())));
769  }
770  // Track Number
771  if (lookup->GetTrackNumber() > 0)
772  {
773  QDomElement tracknum = docroot.createElement("tracknum");
774  item.appendChild(tracknum);
775  tracknum.appendChild(docroot.createTextNode(QString::number(
776  lookup->GetTrackNumber())));
777  }
778  // Popularity
779  if (lookup->GetPopularity() > 0)
780  {
781  QDomElement popularity = docroot.createElement("popularity");
782  item.appendChild(popularity);
783  popularity.appendChild(docroot.createTextNode(QString::number(
784  lookup->GetPopularity())));
785  }
786  // Budget
787  if (lookup->GetBudget() > 0)
788  {
789  QDomElement budget = docroot.createElement("budget");
790  item.appendChild(budget);
791  budget.appendChild(docroot.createTextNode(QString::number(
792  lookup->GetBudget())));
793  }
794  // Revenue
795  if (lookup->GetRevenue() > 0)
796  {
797  QDomElement revenue = docroot.createElement("revenue");
798  item.appendChild(revenue);
799  revenue.appendChild(docroot.createTextNode(QString::number(
800  lookup->GetRevenue())));
801  }
802  // Runtime
803  auto minutes = lookup->GetRuntime();
804  if (minutes > 0min)
805  {
806  QDomElement runtime = docroot.createElement("runtime");
807  item.appendChild(runtime);
808  runtime.appendChild(docroot.createTextNode(QString::number(
809  minutes.count())));
810  }
811  // Runtimesecs
812  auto seconds = lookup->GetRuntimeSeconds();
813  if (seconds > 0s)
814  {
815  QDomElement runtimesecs = docroot.createElement("runtimesecs");
816  item.appendChild(runtimesecs);
817  runtimesecs.appendChild(docroot.createTextNode(QString::number(
818  seconds.count())));
819  }
820 
821  if (!lookup->GetCertification().isEmpty())
822  AddCertifications(lookup, item, docroot);
823  if (!lookup->GetCategories().empty())
824  AddCategories(lookup, item, docroot);
825  if (!lookup->GetStudios().empty())
826  AddStudios(lookup, item, docroot);
827  if (!lookup->GetCountries().empty())
828  AddCountries(lookup, item, docroot);
829 }
830 
832  QDomElement placetoadd,
833  QDomDocument docroot)
834 {
835  QString certstr = lookup->GetCertification();
836  QDomElement certifications = docroot.createElement("certifications");
837  placetoadd.appendChild(certifications);
838 
839  QDomElement cert = docroot.createElement("certification");
840  certifications.appendChild(cert);
841  cert.setAttribute("locale", gCoreContext->GetLocale()->GetCountryCode());
842  cert.setAttribute("name", certstr);
843 }
844 
846  QDomElement placetoadd,
847  QDomDocument docroot)
848 {
849  QStringList cats = lookup->GetCategories();
850  QDomElement categories = docroot.createElement("categories");
851  placetoadd.appendChild(categories);
852 
853  for (const auto & str : std::as_const(cats))
854  {
855  QDomElement cat = docroot.createElement("category");
856  categories.appendChild(cat);
857  cat.setAttribute("type", "genre");
858  cat.setAttribute("name", str);
859  }
860 }
861 
863  QDomElement placetoadd,
864  QDomDocument docroot)
865 {
866  QStringList studs = lookup->GetStudios();
867  QDomElement studios = docroot.createElement("studios");
868  placetoadd.appendChild(studios);
869 
870  for (const auto & str : std::as_const(studs))
871  {
872  QDomElement stud = docroot.createElement("studio");
873  studios.appendChild(stud);
874  stud.setAttribute("name", str);
875  }
876 }
877 
879  QDomElement placetoadd,
880  QDomDocument docroot)
881 {
882  QStringList counts = lookup->GetCountries();
883  QDomElement countries = docroot.createElement("countries");
884  placetoadd.appendChild(countries);
885 
886  for (const auto & str : std::as_const(counts))
887  {
888  QDomElement count = docroot.createElement("country");
889  countries.appendChild(count);
890  count.setAttribute("name", str);
891  }
892 }
893 
894 MetadataLookup* ParseMetadataItem(const QDomElement& item,
895  MetadataLookup *lookup,
896  bool passseas)
897 {
898  if (!lookup)
899  return new MetadataLookup();
900 
901  uint season = 0;
902  uint episode = 0;
903  uint chanid = 0;
904  uint programflags = 0;
905  uint audioproperties = 0;
906  uint videoproperties = 0;
907  uint subtitletype = 0;
908  uint tracknum = 0;
909  uint budget = 0;
910  uint revenue = 0;
911  uint year = 0;
912  uint ratingcount = 0;
913  QString title;
914  QString network;
915  QString status;
916  QString subtitle;
917  QString tagline;
918  QString description;
919  QString certification;
920  QString channum;
921  QString chansign;
922  QString channame;
923  QString chanplaybackfilters;
924  QString recgroup;
925  QString playgroup;
926  QString seriesid;
927  QString programid;
928  QString storagegroup;
929  QString album;
930  QString system;
931  QString inetref;
932  QString collectionref;
933  QString tmsref;
934  QString imdb;
935  QString homepage;
936  QString trailerURL;
937  QString language;
938  QStringList categories;
939  QStringList countries;
940  QStringList studios;
941  float userrating = 0;
942  float popularity = 0;
943  QDate releasedate;
944  QDateTime lastupdated;
945  QDateTime startts;
946  QDateTime endts;
947  QDateTime recstartts;
948  QDateTime recendts;
949  PeopleMap people;
950  ArtworkMap artwork;
951 
952  // Get the easy parses
953  language = item.firstChildElement("language").text();
954  title = Parse::UnescapeHTML(item.firstChildElement("title").text());
955  network = Parse::UnescapeHTML(item.firstChildElement("network").text());
956  status = Parse::UnescapeHTML(item.firstChildElement("status").text());
957  subtitle = Parse::UnescapeHTML(item.firstChildElement("subtitle").text());
958  tagline = Parse::UnescapeHTML(item.firstChildElement("tagline").text());
959  description = Parse::UnescapeHTML(item.firstChildElement("description").text());
960  album = Parse::UnescapeHTML(item.firstChildElement("albumname").text());
961  inetref = item.firstChildElement("inetref").text();
962  collectionref = item.firstChildElement("collectionref").text();
963  tmsref = item.firstChildElement("tmsref").text();
964  imdb = item.firstChildElement("imdb").text();
965  homepage = item.firstChildElement("homepage").text();
966  trailerURL = item.firstChildElement("trailer").text();
967 
968  // ProgramInfo specific parsing
969  chanid = item.firstChildElement("chanid").text().toUInt();
970  channum = item.firstChildElement("channum").text();
971  chansign = item.firstChildElement("chansign").text();
972  channame = item.firstChildElement("channame").text();
973  chanplaybackfilters = item.firstChildElement("chanplaybackfilters").text();
974  recgroup = item.firstChildElement("recgroup").text();
975  playgroup = item.firstChildElement("playgroup").text();
976  seriesid = item.firstChildElement("seriesid").text();
977  programid = item.firstChildElement("programid").text();
978  storagegroup = item.firstChildElement("storagegroup").text();
979  startts = RFC822TimeToQDateTime(item.
980  firstChildElement("startts").text());
981  endts = RFC822TimeToQDateTime(item.
982  firstChildElement("endts").text());
983  recstartts = RFC822TimeToQDateTime(item.
984  firstChildElement("recstartts").text());
985  recendts = RFC822TimeToQDateTime(item.
986  firstChildElement("recendts").text());
987  programflags = item.firstChildElement("programflags").text().toUInt();
988  audioproperties = item.firstChildElement("audioproperties").text().toUInt();
989  videoproperties = item.firstChildElement("videoproperties").text().toUInt();
990  subtitletype = item.firstChildElement("subtitletype").text().toUInt();
991 
992  QString tmpDate = item.firstChildElement("releasedate").text();
993  if (!tmpDate.isEmpty())
994  releasedate = QDate::fromString(tmpDate, "yyyy-MM-dd");
995  lastupdated = RFC822TimeToQDateTime(item.
996  firstChildElement("lastupdated").text());
997 
998  userrating = item.firstChildElement("userrating").text().toFloat();
999  ratingcount = item.firstChildElement("ratingcount").text().toUInt();
1000  tracknum = item.firstChildElement("tracknum").text().toUInt();
1001  popularity = item.firstChildElement("popularity").text().toFloat();
1002  budget = item.firstChildElement("budget").text().toUInt();
1003  revenue = item.firstChildElement("revenue").text().toUInt();
1004  year = item.firstChildElement("year").text().toUInt();
1005  if (!year && !releasedate.isNull())
1006  year = releasedate.toString("yyyy").toUInt();
1007  auto runtime = std::chrono::minutes(item.firstChildElement("runtime").text().toUInt());
1008  auto runtimesecs = std::chrono::seconds(item.firstChildElement("runtimesecs").text().toUInt());
1009 
1010  QDomElement systems = item.firstChildElement("systems");
1011  if (!systems.isNull())
1012  {
1013  QDomElement firstSystem = systems.firstChildElement("system");
1014  if (!firstSystem.isNull())
1015  system = firstSystem.text();
1016  }
1017 
1018  // TODO: Once TMDB supports certification per-locale, come back and match
1019  // locale of myth to certification locale.
1020  QDomElement certifications = item.firstChildElement("certifications");
1021  QVector< QPair<QString,QString> > ratinglist;
1022  if (!certifications.isNull())
1023  {
1024  QDomElement cert = certifications.firstChildElement("certification");
1025  if (!cert.isNull())
1026  {
1027  while (!cert.isNull())
1028  {
1029  if (cert.hasAttribute("locale") && cert.hasAttribute("name"))
1030  {
1031  QPair<QString,QString> newcert(cert.attribute("locale"),
1032  cert.attribute("name"));
1033  ratinglist.append(newcert);
1034  }
1035  cert = cert.nextSiblingElement("certification");
1036  }
1037  }
1038  }
1039  // HACK: To go away when someone supports ratings by locale.
1040  if (!ratinglist.isEmpty())
1041  certification = ratinglist.takeFirst().second;
1042 
1043  // Categories
1044  QDomElement categoriesxml = item.firstChildElement("categories");
1045  if (!categoriesxml.isNull())
1046  {
1047  QDomElement cat = categoriesxml.firstChildElement("category");
1048  if (!cat.isNull())
1049  {
1050  while (!cat.isNull())
1051  {
1052  if (cat.hasAttribute("name"))
1053  categories.append(cat.attribute("name"));
1054  cat = cat.nextSiblingElement("category");
1055  }
1056  }
1057  }
1058 
1059  // Countries
1060  QDomElement countriesxml = item.firstChildElement("countries");
1061  if (!countriesxml.isNull())
1062  {
1063  QDomElement cntry = countriesxml.firstChildElement("country");
1064  if (!cntry.isNull())
1065  {
1066  while (!cntry.isNull())
1067  {
1068  if (cntry.hasAttribute("name"))
1069  countries.append(cntry.attribute("name"));
1070  cntry = cntry.nextSiblingElement("country");
1071  }
1072  }
1073  }
1074 
1075  // Studios
1076  QDomElement studiosxml = item.firstChildElement("studios");
1077  if (!studiosxml.isNull())
1078  {
1079  QDomElement studio = studiosxml.firstChildElement("studio");
1080  if (!studio.isNull())
1081  {
1082  while (!studio.isNull())
1083  {
1084  if (studio.hasAttribute("name"))
1085  studios.append(studio.attribute("name"));
1086  studio = studio.nextSiblingElement("studio");
1087  }
1088  }
1089  }
1090 
1091  // People
1092  QDomElement peoplexml = item.firstChildElement("people");
1093  if (!peoplexml.isNull())
1094  {
1095  people = ParsePeople(peoplexml);
1096  }
1097 
1098  // Artwork
1099  QDomElement artworkxml = item.firstChildElement("images");
1100  if (!artworkxml.isNull())
1101  {
1102  artwork = ParseArtwork(artworkxml);
1103  }
1104 
1105  // Have to handle season and episode a little differently.
1106  // If the query object comes in with a season or episode number,
1107  // we want to pass that through. However, if we are doing a title/subtitle
1108  // lookup, we need to parse for season and episode.
1109  if (passseas)
1110  {
1111  season = lookup->GetSeason();
1112  episode = lookup->GetEpisode();
1113  }
1114 
1115  if (lookup->GetPreferDVDOrdering())
1116  {
1117  if (!season)
1118  {
1119  season = item.firstChildElement("dvdseason").text().toUInt();
1120  }
1121  if (!episode)
1122  {
1123  episode = item.firstChildElement("dvdepisode").text().toUInt();
1124  }
1125  }
1126 
1127  if (!season)
1128  {
1129  season = item.firstChildElement("season").text().toUInt();
1130  }
1131  if (!episode)
1132  {
1133  episode = item.firstChildElement("episode").text().toUInt();
1134  }
1135  LOG(VB_GENERAL, LOG_INFO, QString("Result Found, Season %1 Episode %2")
1136  .arg(season).arg(episode));
1137 
1138  return new MetadataLookup(lookup->GetType(), lookup->GetSubtype(),
1139  lookup->GetData(), lookup->GetStep(), lookup->GetAutomatic(),
1140  lookup->GetHandleImages(), lookup->GetAllowOverwrites(),
1141  lookup->GetAllowGeneric(), lookup->GetPreferDVDOrdering(), lookup->GetHost(),
1142  lookup->GetFilename(), title, network, status, categories, userrating,
1143  ratingcount, language, subtitle, tagline, description, season,
1144  episode, chanid, channum, chansign, channame,
1145  chanplaybackfilters, recgroup, playgroup, seriesid, programid,
1146  storagegroup, startts, endts, recstartts, recendts, programflags,
1147  audioproperties, videoproperties, subtitletype, certification,
1148  countries, popularity, budget, revenue, album, tracknum, system, year,
1149  releasedate, lastupdated, runtime, runtimesecs, inetref, collectionref,
1150  tmsref, imdb, people, studios, homepage, trailerURL, artwork, DownloadMap());
1151 }
1152 
1153 MetadataLookup* ParseMetadataMovieNFO(const QDomElement& item,
1154  MetadataLookup *lookup)
1155 {
1156  if (!lookup)
1157  return new MetadataLookup();
1158 
1159  uint year = 0;
1160  uint season = 0;
1161  uint episode = 0;
1162  QString title;
1163  QString subtitle;
1164  QString tagline;
1165  QString description;
1166  QString inetref;
1167  QString trailer;
1168  QString certification;
1169  float userrating = 0;
1170  QDate releasedate;
1171  QStringList categories;
1172  PeopleMap people;
1173  ArtworkMap artwork;
1174 
1175  // Get the easy parses
1176  if (item.tagName() == "movie")
1177  title = Parse::UnescapeHTML(item.firstChildElement("title").text());
1178  else if (item.tagName() == "episodedetails")
1179  subtitle = Parse::UnescapeHTML(item.firstChildElement("title").text());
1180  userrating = item.firstChildElement("rating").text().toFloat();
1181  year = item.firstChildElement("year").text().toUInt();
1182  season = item.firstChildElement("season").text().toUInt();
1183  episode = item.firstChildElement("episode").text().toUInt();
1184  description = Parse::UnescapeHTML(item.firstChildElement("plot").text());
1185  tagline = Parse::UnescapeHTML(item.firstChildElement("tagline").text());
1186  inetref = item.firstChildElement("id").text();
1187  trailer = item.firstChildElement("trailer").text();
1188  certification = item.firstChildElement("mpaa").text();
1189  categories.append(item.firstChildElement("genre").text());
1190 
1191  QString tmpDate = item.firstChildElement("releasedate").text();
1192  if (!tmpDate.isEmpty())
1193  releasedate = QDate::fromString(tmpDate, "yyyy-MM-dd");
1194  else if (year > 0)
1195  releasedate = QDate::fromString(QString::number(year), "yyyy");
1196 
1197  static const QRegularExpression kAlphaRE { "[A-Za-z]" };
1198  auto runtime =
1199  std::chrono::minutes(item.firstChildElement("runtime").text()
1200  .remove(kAlphaRE)
1201  .trimmed().toUInt());
1202 
1203  QDomElement actor = item.firstChildElement("actor");
1204  if (!actor.isNull())
1205  {
1206  while (!actor.isNull())
1207  {
1208  PersonInfo info;
1209  info.name = actor.firstChildElement("name").text();
1210  info.role = actor.firstChildElement("role").text();
1211  info.thumbnail = actor.firstChildElement("thumb").text();
1212  people.insert(kPersonActor, info);
1213  actor = actor.nextSiblingElement("actor");
1214  }
1215  }
1216 
1217  QString director = item.firstChildElement("director").text();
1218  if (!director.isEmpty())
1219  {
1220  PersonInfo info;
1221  info.name = director;
1222  people.insert(kPersonDirector, info);
1223  }
1224 
1225  return new MetadataLookup(lookup->GetType(), lookup->GetSubtype(),
1226  lookup->GetData(), lookup->GetStep(),
1227  lookup->GetAutomatic(), lookup->GetHandleImages(),
1228  lookup->GetAllowOverwrites(), lookup->GetAllowGeneric(),
1229  lookup->GetPreferDVDOrdering(), lookup->GetHost(),
1230  lookup->GetFilename(), title, categories,
1231  userrating, subtitle, tagline, description, season, episode,
1232  certification, year, releasedate, runtime, runtime,
1233  inetref, people, trailer, artwork, DownloadMap());
1234 }
1235 
1236 PeopleMap ParsePeople(const QDomElement& people)
1237 {
1238  PeopleMap ret;
1239 
1240  QDomElement person = people.firstChildElement("person");
1241  if (!person.isNull())
1242  {
1243  while (!person.isNull())
1244  {
1245  if (person.hasAttribute("job"))
1246  {
1247  QString jobstring = person.attribute("job");
1249  if (jobstring.toLower() == "actor")
1250  type = kPersonActor; // NOLINT(bugprone-branch-clone)
1251  else if (jobstring.toLower() == "author")
1252  type = kPersonAuthor;
1253  else if (jobstring.toLower() == "producer")
1255  else if (jobstring.toLower() == "executive producer")
1257  else if (jobstring.toLower() == "director")
1259  else if (jobstring.toLower() == "cinematographer")
1261  else if (jobstring.toLower() == "composer")
1263  else if (jobstring.toLower() == "editor")
1264  type = kPersonEditor;
1265  else if (jobstring.toLower() == "casting")
1267  else if (jobstring.toLower() == "artist")
1268  type = kPersonArtist;
1269  else if (jobstring.toLower() == "album artist")
1271  else if (jobstring.toLower() == "guest star")
1273  else
1274  type = kPersonActor;
1275 
1276  PersonInfo info;
1277  if (person.hasAttribute("name"))
1278  info.name = person.attribute("name");
1279  if (person.hasAttribute("character"))
1280  info.role = person.attribute("character");
1281  if (person.hasAttribute("thumb"))
1282  info.thumbnail = person.attribute("thumb");
1283  if (person.hasAttribute("url"))
1284  info.url = person.attribute("url");
1285 
1286  ret.insert(type,info);
1287  }
1288  person = person.nextSiblingElement("person");
1289  }
1290  }
1291  return ret;
1292 }
1293 
1294 ArtworkMap ParseArtwork(const QDomElement& artwork)
1295 {
1296  ArtworkMap ret;
1297 
1298  QDomElement image = artwork.firstChildElement("image");
1299  if (!image.isNull())
1300  {
1301  while (!image.isNull())
1302  {
1303  if (image.hasAttribute("type"))
1304  {
1305  QString typestring = image.attribute("type");
1307  if (typestring.toLower() == "coverart")
1308  type = kArtworkCoverart; // NOLINT(bugprone-branch-clone)
1309  else if (typestring.toLower() == "fanart")
1310  type = kArtworkFanart;
1311  else if (typestring.toLower() == "banner")
1312  type = kArtworkBanner;
1313  else if (typestring.toLower() == "screenshot")
1315  else if (typestring.toLower() == "poster")
1316  type = kArtworkPoster;
1317  else if (typestring.toLower() == "back cover")
1319  else if (typestring.toLower() == "inside cover")
1321  else if (typestring.toLower() == "cd image")
1323  else
1325 
1326  ArtworkInfo info;
1327  if (image.hasAttribute("thumb"))
1328  info.thumbnail = image.attribute("thumb");
1329  if (image.hasAttribute("url"))
1330  info.url = image.attribute("url");
1331  if (image.hasAttribute("width"))
1332  info.width = image.attribute("width").toUInt();
1333  else
1334  info.width = 0;
1335  if (image.hasAttribute("height"))
1336  info.height = image.attribute("height").toUInt();
1337  else
1338  info.height = 0;
1339 
1340  ret.insert(type,info);
1341  }
1342  image = image.nextSiblingElement("image");
1343  }
1344  }
1345  return ret;
1346 }
1347 
1348 int editDistance( const QString& s, const QString& t )
1349 {
1350 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
1351 #define D( i, j ) d[(i) * n + (j)]
1352  size_t m = s.length() + 1;
1353  size_t n = t.length() + 1;
1354  int *d = new int[m * n];
1355 
1356  for ( size_t i = 0; i < m; i++ )
1357  D( i, 0 ) = i;
1358  for ( size_t j = 0; j < n; j++ )
1359  D( 0, j ) = j;
1360  for ( size_t i = 1; i < m; i++ )
1361  {
1362  for ( size_t j = 1; j < n; j++ )
1363  {
1364  if (
1365 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1366  s[static_cast<int>(i) - 1] == t[static_cast<int>(j) - 1]
1367 #else
1368  s[i - 1] == t[j - 1]
1369 #endif
1370  )
1371  D( i, j ) = D( i - 1, j - 1 );
1372  else
1373  {
1374  int x = D( i - 1, j );
1375  int y = D( i - 1, j - 1 );
1376  int z = D( i, j - 1 );
1377  D( i, j ) = 1 + std::min({x, y, z});
1378  }
1379  }
1380  }
1381  int result = D( m - 1, n - 1 );
1382  delete[] d;
1383  return result;
1384 #undef D
1385 }
1386 
1387 QString nearestName(const QString& actual, const QStringList& candidates)
1388 {
1389  int deltaBest = 10000;
1390  int numBest = 0;
1391  int tolerance = gCoreContext->GetNumSetting("MetadataLookupTolerance", 5);
1392  QString best;
1393 
1394  QStringList::ConstIterator i = candidates.begin();
1395  while ( i != candidates.end() )
1396  {
1397  QString candidate = *i;
1398  int delta = editDistance( actual.toLower(), candidate.toLower() );
1399  if ( delta < deltaBest )
1400  {
1401  deltaBest = delta;
1402  numBest = 1;
1403  best = *i;
1404  }
1405  else if ( delta == deltaBest )
1406  {
1407  numBest++;
1408  }
1409  ++i;
1410  }
1411 
1412  if ( numBest == 1 && deltaBest <= tolerance &&
1413  actual.length() + best.length() >= 5 )
1414  return best;
1415  return {};
1416 }
1417 
1418 QDateTime RFC822TimeToQDateTime(const QString& t)
1419 {
1420  QMap<QString, int> TimezoneOffsets;
1421 
1422  if (t.size() < 20)
1423  return {};
1424 
1425  QString time = t.simplified();
1426  short int hoursShift = 0;
1427  short int minutesShift = 0;
1428 
1429  QStringList tmp = time.split(' ');
1430  if (tmp.isEmpty())
1431  return {};
1432  static const QRegularExpression kNonDigitRE { "\\D" };
1433  if (tmp.at(0).contains(kNonDigitRE))
1434  tmp.removeFirst();
1435  if (tmp.size() != 5)
1436  return {};
1437  QString ltimezone = tmp.takeAt(tmp.size() -1);
1438  if (ltimezone.size() == 5)
1439  {
1440  bool ok = false;
1441  int tz = ltimezone.toInt(&ok);
1442  if(ok)
1443  {
1444  hoursShift = tz / 100;
1445  minutesShift = tz % 100;
1446  }
1447  }
1448  else
1449  hoursShift = TimezoneOffsets.value(ltimezone, 0);
1450 
1451  if (tmp.at(0).size() == 1)
1452  tmp[0].prepend("0");
1453  tmp [1].truncate(3);
1454 
1455  time = tmp.join(" ");
1456 
1457  QDateTime result;
1458  if (tmp.at(2).size() == 4)
1459  result = QLocale::c().toDateTime(time, "dd MMM yyyy hh:mm:ss");
1460  else
1461  result = QLocale::c().toDateTime(time, "dd MMM yy hh:mm:ss");
1462  if (result.isNull() || !result.isValid())
1463  return {};
1464  result = result.addSecs(hoursShift * 3600 * (-1) + minutesShift *60 * (-1));
1465  result.setTimeSpec(Qt::UTC);
1466  return result;
1467 }
MetadataLookup::m_season
uint m_season
Definition: metadatacommon.h:401
PeopleType
PeopleType
Definition: metadatacommon.h:69
MetadataLookup::m_network
QString m_network
Definition: metadatacommon.h:390
MetadataLookup::m_system
QString m_system
Definition: metadatacommon.h:433
VideoArtworkType
VideoArtworkType
Definition: metadataimagehelper.h:10
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:84
MetadataLookup::GetTMSref
QString GetTMSref() const
Definition: metadatacommon.h:359
MetadataLookup::GetTrackNumber
uint GetTrackNumber() const
Definition: metadatacommon.h:343
MetadataLookup::m_tagline
const QString m_tagline
Definition: metadatacommon.h:399
MetadataLookup::m_people
const PeopleMap m_people
Definition: metadatacommon.h:450
kArtworkInsideCover
@ kArtworkInsideCover
Definition: metadataimagehelper.h:17
MetadataLookup::m_recStartTs
const QDateTime m_recStartTs
Definition: metadatacommon.h:415
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
ProgramInfo::GetHostname
QString GetHostname(void) const
Definition: programinfo.h:421
kMetadataRecording
@ kMetadataRecording
Definition: metadatacommon.h:44
MetadataLookup::m_filename
QString m_filename
Definition: metadatacommon.h:387
MetadataType
MetadataType
Definition: metadatacommon.h:42
MetadataLookup::GetTitle
QString GetTitle() const
Definition: metadatacommon.h:299
MetadataLookup::m_year
uint m_year
Definition: metadatacommon.h:436
MetadataLookup::m_releaseDate
const QDate m_releaseDate
Definition: metadatacommon.h:437
MythCoreContext::GetLocale
MythLocale * GetLocale(void) const
Definition: mythcorecontext.cpp:1758
ArtworkList
QList< ArtworkInfo > ArtworkList
Definition: metadataimagehelper.h:30
MetadataLookup::GetSubtype
LookupType GetSubtype() const
Definition: metadatacommon.h:287
MetadataLookup::m_collectionRef
QString m_collectionRef
Definition: metadatacommon.h:444
MetadataLookup::GetNetwork
QString GetNetwork() const
Definition: metadatacommon.h:308
Parse::UnescapeHTML
static QString UnescapeHTML(const QString &escaped)
Definition: rssparse.cpp:1133
ProgramInfo::GetChannelName
QString GetChannelName(void) const
This is the channel name in the local market, i.e.
Definition: programinfo.h:386
MetadataLookup::m_runtimeSecs
std::chrono::seconds m_runtimeSecs
Definition: metadatacommon.h:440
kPersonAuthor
@ kPersonAuthor
Definition: metadatacommon.h:71
hardwareprofile.devicelist.cat
def cat(file_name)
Definition: devicelist.py:95
ProgramInfo::GetChanNum
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
Definition: programinfo.h:376
PersonInfo::role
QString role
Definition: metadatacommon.h:36
MetadataLookup::GetLanguage
QString GetLanguage() const
Definition: metadatacommon.h:304
rssparse.h
MetadataLookup::m_chanNum
const QString m_chanNum
Definition: metadatacommon.h:404
kPersonProducer
@ kPersonProducer
Definition: metadatacommon.h:73
MetadataLookup::GetAlbumTitle
QString GetAlbumTitle() const
Definition: metadatacommon.h:342
MetadataLookup::m_seriesId
const QString m_seriesId
Definition: metadatacommon.h:410
ProgramInfo::GetChannelSchedulingID
QString GetChannelSchedulingID(void) const
This is the unique programming identifier of a channel.
Definition: programinfo.h:383
ProgramInfo::GetCategory
QString GetCategory(void) const
Definition: programinfo.h:369
MetadataLookup::m_homepage
const QString m_homepage
Definition: metadatacommon.h:454
MetadataLookup::GetSeriesId
QString GetSeriesId() const
Definition: metadatacommon.h:323
MetadataLookup::GetArtwork
ArtworkList GetArtwork(VideoArtworkType type) const
Definition: metadatacommon.cpp:331
MetadataLookup::m_endTs
const QDateTime m_endTs
Definition: metadatacommon.h:414
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
ProgramInfo::GetScheduledEndTime
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:397
kPersonEditor
@ kPersonEditor
Definition: metadatacommon.h:77
MetadataLookup::m_chanPlaybackFilters
const QString m_chanPlaybackFilters
Definition: metadatacommon.h:407
MetadataLookup::GetCertification
QString GetCertification() const
Definition: metadatacommon.h:335
MetadataLookup::m_chanId
uint m_chanId
Definition: metadatacommon.h:403
ArtworkInfo::width
uint width
Definition: metadataimagehelper.h:26
kArtworkBackCover
@ kArtworkBackCover
Definition: metadataimagehelper.h:16
ProgramInfo::GetRecordingEndTime
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:412
ProgramInfo::GetProgramFlags
uint32_t GetProgramFlags(void) const
Definition: programinfo.h:470
ProgramInfo::GetRecordingGroup
QString GetRecordingGroup(void) const
Definition: programinfo.h:419
kArtworkCDImage
@ kArtworkCDImage
Definition: metadataimagehelper.h:18
MetadataLookup::GetBudget
uint GetBudget() const
Definition: metadatacommon.h:338
MetadataLookup::GetAudioProperties
uint GetAudioProperties() const
Definition: metadatacommon.h:331
MetadataLookup::m_storageGroup
const QString m_storageGroup
Definition: metadatacommon.h:412
MetadataLookup::m_playGroup
const QString m_playGroup
Definition: metadatacommon.h:409
MetadataLookup::GetTrailerURL
QString GetTrailerURL() const
Definition: metadatacommon.h:368
MetadataLookup::GetPreferDVDOrdering
bool GetPreferDVDOrdering() const
Definition: metadatacommon.h:313
MetadataLookup::toMap
void toMap(InfoMap &map)
Definition: metadatacommon.cpp:348
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:404
kPersonGuestStar
@ kPersonGuestStar
Definition: metadatacommon.h:81
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
MetadataLookup::GetStep
LookupStep GetStep() const
Definition: metadatacommon.h:289
nearestName
QString nearestName(const QString &actual, const QStringList &candidates)
Definition: metadatacommon.cpp:1387
MetadataLookup
Definition: metadatacommon.h:87
InfoMap
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
MetadataLookup::m_subtitle
QString m_subtitle
Definition: metadatacommon.h:398
RFC822TimeToQDateTime
QDateTime RFC822TimeToQDateTime(const QString &t)
Definition: metadatacommon.cpp:1418
AddCertifications
void AddCertifications(MetadataLookup *lookup, QDomElement placetoadd, QDomDocument docroot)
Definition: metadatacommon.cpp:831
MetadataLookup::GetRatingCount
uint GetRatingCount() const
Definition: metadatacommon.h:303
MetadataLookup::m_inetRef
QString m_inetRef
Definition: metadatacommon.h:443
ProgramInfo::GetInetRef
QString GetInetRef(void) const
Definition: programinfo.h:437
MetadataLookup::GetChanSign
QString GetChanSign() const
Definition: metadatacommon.h:318
ProgramInfo::GetYearOfInitialRelease
uint GetYearOfInitialRelease(void) const
Definition: programinfo.h:423
kPersonCastingDirector
@ kPersonCastingDirector
Definition: metadatacommon.h:78
PersonInfo::thumbnail
QString thumbnail
Definition: metadatacommon.h:37
MetadataLookup::m_baseTitle
QString m_baseTitle
Definition: metadatacommon.h:389
MetadataLookup::m_runtime
std::chrono::minutes m_runtime
Definition: metadatacommon.h:439
programinfo.h
ProgramInfo::GetScheduledStartTime
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:390
mythlogging.h
MythLocale::GetCountryCode
QString GetCountryCode() const
Definition: mythlocale.cpp:57
MetadataLookup::GetEpisode
uint GetEpisode() const
Definition: metadatacommon.h:315
MetadataLookup::GetDescription
QString GetDescription() const
Definition: metadatacommon.h:312
MetadataLookup::GetIMDB
QString GetIMDB() const
Definition: metadatacommon.h:358
MetadataLookup::m_revenue
uint m_revenue
Definition: metadatacommon.h:426
kPersonActor
@ kPersonActor
Definition: metadatacommon.h:70
MetadataLookup::GetAllowOverwrites
bool GetAllowOverwrites() const
Definition: metadatacommon.h:294
MetadataLookup::m_lastUpdated
const QDateTime m_lastUpdated
Definition: metadatacommon.h:438
ArtworkInfo
Definition: metadataimagehelper.h:21
ParsePeople
PeopleMap ParsePeople(const QDomElement &people)
Definition: metadatacommon.cpp:1236
hardwareprofile.i18n.t
t
Definition: i18n.py:36
PersonInfo::url
QString url
Definition: metadatacommon.h:38
MetadataLookup::m_album
QString m_album
Definition: metadatacommon.h:429
RefCountedList
General purpose reference counted list.
Definition: referencecounterlist.h:55
MetadataLookup::GetData
QVariant GetData() const
Definition: metadatacommon.h:288
MetadataLookup::GetStartTS
QDateTime GetStartTS() const
Definition: metadatacommon.h:326
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:361
ProgramInfo::GetDescription
QString GetDescription(void) const
Definition: programinfo.h:365
kLookupData
@ kLookupData
Definition: metadatacommon.h:29
kArtworkPoster
@ kArtworkPoster
Definition: metadataimagehelper.h:15
kPersonDirector
@ kPersonDirector
Definition: metadatacommon.h:72
ParseArtwork
ArtworkMap ParseArtwork(const QDomElement &artwork)
Definition: metadatacommon.cpp:1294
CreateMetadataXMLItem
void CreateMetadataXMLItem(MetadataLookup *lookup, QDomElement placetoadd, QDomDocument docroot)
Definition: metadatacommon.cpp:480
MetadataLookup::m_artwork
const ArtworkMap m_artwork
Definition: metadatacommon.h:458
MetadataLookup::m_episode
uint m_episode
Definition: metadatacommon.h:402
MetadataLookup::GetType
MetadataType GetType() const
Definition: metadatacommon.h:286
x0
static int x0
Definition: metadatacommon.cpp:19
MetadataLookup::m_countries
const QStringList m_countries
Definition: metadatacommon.h:423
MetadataLookup::GetChanNum
QString GetChanNum() const
Definition: metadatacommon.h:317
MetadataLookup::m_studios
const QStringList m_studios
Definition: metadatacommon.h:451
MetadataLookup::GetRecGroup
QString GetRecGroup() const
Definition: metadatacommon.h:321
kArtworkFanart
@ kArtworkFanart
Definition: metadataimagehelper.h:12
MetadataLookup::GetSubtitle
QString GetSubtitle() const
Definition: metadatacommon.h:310
MetadataLookup::GetCountries
QStringList GetCountries() const
Definition: metadatacommon.h:336
MetadataLookup::GetLastUpdated
QDateTime GetLastUpdated() const
Definition: metadatacommon.h:351
MetadataLookup::GetVideoProperties
uint GetVideoProperties() const
Definition: metadatacommon.h:332
MetadataLookup::GetRecEndTS
QDateTime GetRecEndTS() const
Definition: metadatacommon.h:329
ProgramInfo::GetAudioProperties
uint GetAudioProperties(void) const
Definition: programinfo.h:497
MetadataLookup::m_recEndTs
const QDateTime m_recEndTs
Definition: metadatacommon.h:416
kPersonComposer
@ kPersonComposer
Definition: metadatacommon.h:76
MetadataLookup::GetPeople
QList< PersonInfo > GetPeople(PeopleType type) const
Definition: metadatacommon.cpp:315
ProgramInfo::GetPlaybackGroup
QString GetPlaybackGroup(void) const
Definition: programinfo.h:420
kPersonAlbumArtist
@ kPersonAlbumArtist
Definition: metadatacommon.h:80
mythlocale.h
ProgramInfo::GetChannelPlaybackFilters
QString GetChannelPlaybackFilters(void) const
Definition: programinfo.h:387
MetadataLookup::GetCollectionref
QString GetCollectionref() const
Definition: metadatacommon.h:357
MetadataLookup::m_certification
const QString m_certification
Definition: metadatacommon.h:422
MetadataLookup::GetHandleImages
bool GetHandleImages() const
Definition: metadatacommon.h:293
uint
unsigned int uint
Definition: compat.h:81
MetadataLookup::GetUserRating
float GetUserRating() const
Definition: metadatacommon.h:302
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
ProgramInfo::GetSeriesID
QString GetSeriesID(void) const
Definition: programinfo.h:435
MetadataLookup::m_popularity
float m_popularity
Definition: metadatacommon.h:424
MetadataLookup::m_imdb
QString m_imdb
Definition: metadatacommon.h:446
MetadataLookup::GetAllowGeneric
bool GetAllowGeneric() const
Definition: metadatacommon.h:295
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:912
ProgramInfo::GetStorageGroup
QString GetStorageGroup(void) const
Definition: programinfo.h:422
ProgramInfo::GetOriginalAirDate
QDate GetOriginalAirDate(void) const
Definition: programinfo.h:428
MetadataLookup::GetSeason
uint GetSeason() const
Definition: metadatacommon.h:314
PeopleMap
QMultiMap< PeopleType, PersonInfo > PeopleMap
Definition: metadatacommon.h:85
MetadataLookup::GetFilename
QString GetFilename() const
Definition: metadatacommon.h:298
ProgramInfo::GetVideoProperties
uint GetVideoProperties(void) const
Definition: programinfo.h:495
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:34
kUnknownVideo
@ kUnknownVideo
Definition: metadatacommon.h:54
MetadataLookup::GetPopularity
float GetPopularity() const
Definition: metadatacommon.h:337
MetadataLookup::GetCategories
QStringList GetCategories() const
Definition: metadatacommon.h:301
MetadataLookup::m_categories
const QStringList m_categories
Definition: metadatacommon.h:392
MetadataLookup::GetStatus
QString GetStatus() const
Definition: metadatacommon.h:309
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:372
MetadataLookup::GetRuntime
std::chrono::minutes GetRuntime() const
Definition: metadatacommon.h:352
MetadataLookup::m_title
QString m_title
Definition: metadatacommon.h:388
ProgramInfo::GetEpisode
uint GetEpisode(void) const
Definition: programinfo.h:367
MetadataLookup::m_description
const QString m_description
Definition: metadatacommon.h:400
MetadataLookup::GetChanPlaybackFilters
QString GetChanPlaybackFilters() const
Definition: metadatacommon.h:320
MetadataLookup::m_tmsRef
QString m_tmsRef
Definition: metadatacommon.h:445
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
mythmiscutil.h
MetadataLookup::GetStorageGroup
QString GetStorageGroup() const
Definition: metadatacommon.h:325
ProgramInfo::GetLastModifiedTime
QDateTime GetLastModifiedTime(void) const
Definition: programinfo.h:429
ProgramInfo::GetSeason
uint GetSeason(void) const
Definition: programinfo.h:366
mythcorecontext.h
AddCountries
void AddCountries(MetadataLookup *lookup, QDomElement placetoadd, QDomDocument docroot)
Definition: metadatacommon.cpp:878
MetadataLookup::m_language
const QString m_language
Definition: metadatacommon.h:395
MetadataLookup::GetTagline
QString GetTagline() const
Definition: metadatacommon.h:311
MetadataLookup::GetRevenue
uint GetRevenue() const
Definition: metadatacommon.h:339
MetadataLookup::m_programid
const QString m_programid
Definition: metadatacommon.h:411
MetadataLookup::m_trailerURL
const QString m_trailerURL
Definition: metadatacommon.h:455
MetadataLookup::GetInetref
QString GetInetref() const
Definition: metadatacommon.h:356
MetadataLookup::m_chanName
const QString m_chanName
Definition: metadatacommon.h:406
MetadataLookup::MetadataLookup
MetadataLookup(void)
Definition: metadatacommon.h:90
PersonInfo::name
QString name
Definition: metadatacommon.h:35
std
Definition: mythchrono.h:23
MetadataLookup::GetStudios
QStringList GetStudios() const
Definition: metadatacommon.h:364
ArtworkInfo::height
uint height
Definition: metadataimagehelper.h:27
kPersonExecProducer
@ kPersonExecProducer
Definition: metadatacommon.h:74
MetadataLookup::GetRecStartTS
QDateTime GetRecStartTS() const
Definition: metadatacommon.h:328
AddCategories
void AddCategories(MetadataLookup *lookup, QDomElement placetoadd, QDomDocument docroot)
Definition: metadatacommon.cpp:845
kPersonCinematographer
@ kPersonCinematographer
Definition: metadatacommon.h:75
MetadataLookup::m_budget
uint m_budget
Definition: metadatacommon.h:425
MetadataLookup::m_ratingCount
uint m_ratingCount
Definition: metadatacommon.h:394
MetadataLookup::GetSubtitleType
uint GetSubtitleType() const
Definition: metadatacommon.h:333
LookupType
LookupType
Definition: metadatacommon.h:50
CreateMetadataXML
QDomDocument CreateMetadataXML(MetadataLookupList list)
Definition: metadatacommon.cpp:440
kArtworkBanner
@ kArtworkBanner
Definition: metadataimagehelper.h:13
MythDate::kDateFull
@ kDateFull
Default local time.
Definition: mythdate.h:19
DownloadMap
QMap< VideoArtworkType, ArtworkInfo > DownloadMap
Definition: metadatacommon.h:84
kPersonArtist
@ kPersonArtist
Definition: metadatacommon.h:79
ArtworkMap
QMultiMap< VideoArtworkType, ArtworkInfo > ArtworkMap
Definition: metadataimagehelper.h:31
ParseMetadataItem
MetadataLookup * ParseMetadataItem(const QDomElement &item, MetadataLookup *lookup, bool passseas)
Definition: metadatacommon.cpp:894
MetadataLookup::m_status
QString m_status
Definition: metadatacommon.h:391
ProgramInfo::GetProgramID
QString GetProgramID(void) const
Definition: programinfo.h:436
MetadataLookup::GetReleaseDate
QDate GetReleaseDate() const
Definition: metadatacommon.h:350
MetadataLookup::GetRuntimeSeconds
std::chrono::seconds GetRuntimeSeconds() const
Definition: metadatacommon.h:353
MetadataLookup::m_trackNum
uint m_trackNum
Definition: metadatacommon.h:430
MetadataLookup::m_startTs
const QDateTime m_startTs
Definition: metadatacommon.h:413
ArtworkInfo::thumbnail
QString thumbnail
Definition: metadataimagehelper.h:24
MetadataLookup::GetChanId
uint GetChanId() const
Definition: metadatacommon.h:316
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
kArtworkScreenshot
@ kArtworkScreenshot
Definition: metadataimagehelper.h:14
MetadataLookup::GetPlayGroup
QString GetPlayGroup() const
Definition: metadatacommon.h:322
MetadataLookup::GetAutomatic
bool GetAutomatic() const
Definition: metadatacommon.h:290
MetadataLookup::m_recGroup
const QString m_recGroup
Definition: metadatacommon.h:408
MetadataLookup::GetHomepage
QString GetHomepage() const
Definition: metadatacommon.h:367
ParseMetadataMovieNFO
MetadataLookup * ParseMetadataMovieNFO(const QDomElement &item, MetadataLookup *lookup)
Definition: metadatacommon.cpp:1153
MetadataLookup::GetHost
QString GetHost() const
Definition: metadatacommon.h:305
MetadataLookup::GetChanName
QString GetChanName() const
Definition: metadatacommon.h:319
AddStudios
void AddStudios(MetadataLookup *lookup, QDomElement placetoadd, QDomDocument docroot)
Definition: metadatacommon.cpp:862
ProgramInfo::GetBasename
QString GetBasename(void) const
Definition: programinfo.h:344
ProgramInfo::GetSubtitleType
uint GetSubtitleType(void) const
Definition: programinfo.h:493
build_compdb.filename
filename
Definition: build_compdb.py:21
MetadataLookup::GetProgramFlags
uint GetProgramFlags() const
Definition: metadatacommon.h:330
D
#define D(i, j)
PersonInfo
Definition: metadatacommon.h:33
MetadataLookup::GetEndTS
QDateTime GetEndTS() const
Definition: metadatacommon.h:327
metadatacommon.h
kArtworkCoverart
@ kArtworkCoverart
Definition: metadataimagehelper.h:11
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:26
LookupFromProgramInfo
MetadataLookup * LookupFromProgramInfo(ProgramInfo *pginfo)
Definition: metadatacommon.cpp:410
MetadataLookup::GetProgramId
QString GetProgramId() const
Definition: metadatacommon.h:324
MetadataLookup::m_chanSign
const QString m_chanSign
Definition: metadatacommon.h:405
editDistance
int editDistance(const QString &s, const QString &t)
Definition: metadatacommon.cpp:1348
ArtworkInfo::url
QString url
Definition: metadataimagehelper.h:25
LookupStep
LookupStep
Definition: metadatacommon.h:27
ProgramInfo::GetSubtitle
QString GetSubtitle(void) const
Definition: programinfo.h:363
MetadataLookup::m_userRating
float m_userRating
Definition: metadatacommon.h:393
ProgramInfo::GetStars
float GetStars(void) const
Definition: programinfo.h:442