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