MythTV  master
metadatadownload.cpp
Go to the documentation of this file.
1 // C/C++
2 #include <cstdlib>
3 
4 // qt
5 #include <QCoreApplication>
6 #include <QEvent>
7 #include <QDir>
8 #include <QUrl>
9 
10 // myth
12 #include "libmythbase/mythdirs.h"
16 #include "libmythbase/remotefile.h"
18 #include "libmythui/mythuihelper.h"
19 
20 #include "metadatadownload.h"
21 #include "metadatafactory.h"
22 
23 const QEvent::Type MetadataLookupEvent::kEventType =
24  (QEvent::Type) QEvent::registerEventType();
25 
26 const QEvent::Type MetadataLookupFailure::kEventType =
27  (QEvent::Type) QEvent::registerEventType();
28 
30 {
31  cancel();
32  wait();
33 }
34 
40 {
41  // Add a lookup to the queue
42  QMutexLocker lock(&m_mutex);
43 
44  m_lookupList.append(lookup);
45  lookup->DecrRef();
46  if (!isRunning())
47  start();
48 }
49 
55 {
56  // Add a lookup to the queue
57  QMutexLocker lock(&m_mutex);
58 
59  m_lookupList.prepend(lookup);
60  lookup->DecrRef();
61  if (!isRunning())
62  start();
63 }
64 
66 {
67  QMutexLocker lock(&m_mutex);
68 
69  m_lookupList.clear();
70  m_parent = nullptr;
71 }
72 
74 {
75  RunProlog();
76 
77  while (true)
78  {
79  m_mutex.lock();
80  if (m_lookupList.isEmpty())
81  {
82  // no more to process, we're done
83  m_mutex.unlock();
84  break;
85  }
86  // Ref owns the MetadataLookup object for the duration of the loop
87  // and it will be deleted automatically when the loop completes
89  m_mutex.unlock();
90  MetadataLookup *lookup = ref;
91  MetadataLookupList list;
92 
93  // Go go gadget Metadata Lookup
94  if (lookup->GetType() == kMetadataVideo ||
95  lookup->GetType() == kMetadataRecording)
96  {
97  // First, look for mxml and nfo files in video storage groups
98  if (lookup->GetType() == kMetadataVideo &&
99  !lookup->GetFilename().isEmpty())
100  {
101  QString mxml = getMXMLPath(lookup->GetFilename());
102  QString nfo = getNFOPath(lookup->GetFilename());
103 
104  if (!mxml.isEmpty())
105  list = readMXML(mxml, lookup);
106  else if (!nfo.isEmpty())
107  list = readNFO(nfo, lookup);
108  }
109 
110  // If nothing found, create lookups based on filename
111  if (list.isEmpty())
112  {
113  if (lookup->GetSubtype() == kProbableTelevision)
114  {
115  list = handleTelevision(lookup);
116  if ((findExactMatchCount(list, lookup->GetBaseTitle(), true) == 0) ||
117  (list.size() > 1 && !lookup->GetAutomatic()))
118  {
119  // There are no exact match prospects with artwork from TV search,
120  // so add in movies, where we might find a better match.
121  // In case of manual mode and ambiguous result, add it as well.
122  list.append(handleMovie(lookup));
123  }
124  }
125  else if (lookup->GetSubtype() == kProbableMovie)
126  {
127  list = handleMovie(lookup);
128  if ((findExactMatchCount(list, lookup->GetBaseTitle(), true) == 0) ||
129  (list.size() > 1 && !lookup->GetAutomatic()))
130  {
131  // There are no exact match prospects with artwork from Movie search
132  // so add in television, where we might find a better match.
133  // In case of manual mode and ambiguous result, add it as well.
134  list.append(handleTelevision(lookup));
135  }
136  }
137  else
138  {
139  // will try both movie and TV
140  list = handleVideoUndetermined(lookup);
141  }
142  }
143  }
144  else if (lookup->GetType() == kMetadataGame)
145  list = handleGame(lookup);
146 
147  // inform parent we have lookup ready for it
148  if (m_parent && !list.isEmpty())
149  {
150  // If there's only one result, don't bother asking
151  // our parent about it, just add it to the back of
152  // the queue in kLookupData mode.
153  if (list.count() == 1 && list[0]->GetStep() == kLookupSearch)
154  {
155  MetadataLookup *newlookup = list.takeFirst();
156 
157  newlookup->SetStep(kLookupData);
158  prependLookup(newlookup);
159  // Type may have changed
160  LookupType ret = GuessLookupType(newlookup);
161  if (ret != kUnknownVideo)
162  {
163  newlookup->SetSubtype(ret);
164  }
165  continue;
166  }
167 
168  // If we're in automatic mode, we need to make
169  // these decisions on our own. Pass to title match.
170  if (list[0]->GetAutomatic() && list.count() > 1
171  && list[0]->GetStep() == kLookupSearch)
172  {
173  MetadataLookup *bestLookup = findBestMatch(list, lookup->GetBaseTitle());
174  if (bestLookup)
175  {
176  MetadataLookup *newlookup = bestLookup;
177 
178  // pass through automatic type
179  newlookup->SetAutomatic(true);
180  // bestlookup is owned by list, we need an extra reference
181  newlookup->IncrRef();
182  newlookup->SetStep(kLookupData);
183  // Type may have changed
184  LookupType ret = GuessLookupType(newlookup);
185  if (ret != kUnknownVideo)
186  {
187  newlookup->SetSubtype(ret);
188  }
189  prependLookup(newlookup);
190  continue;
191  }
192 
193  // Experimental:
194  // If nothing matches, always return the first found item
195  if (qEnvironmentVariableIsSet("EXPERIMENTAL_METADATA_GRAB"))
196  {
197  MetadataLookup *newlookup = list.takeFirst();
198 
199  // pass through automatic type
200  newlookup->SetAutomatic(true); // ### XXX RER
201  newlookup->SetStep(kLookupData);
202  // Type may have changed
203  LookupType ret = GuessLookupType(newlookup);
204  if (ret != kUnknownVideo)
205  {
206  newlookup->SetSubtype(ret);
207  }
208  prependLookup(newlookup);
209  continue;
210  }
211 
212  // nothing more we can do in automatic mode
213  QCoreApplication::postEvent(m_parent,
214  new MetadataLookupFailure(MetadataLookupList() << lookup));
215  continue;
216  }
217 
218  LOG(VB_GENERAL, LOG_INFO,
219  QString("Returning Metadata Results: %1 %2 %3")
220  .arg(lookup->GetBaseTitle()).arg(lookup->GetSeason())
221  .arg(lookup->GetEpisode()));
222  QCoreApplication::postEvent(m_parent,
223  new MetadataLookupEvent(list));
224  }
225  else
226  {
227  if (list.isEmpty())
228  {
229  LOG(VB_GENERAL, LOG_INFO,
230  QString("Metadata Lookup Failed: No Results %1 %2 %3")
231  .arg(lookup->GetBaseTitle()).arg(lookup->GetSeason())
232  .arg(lookup->GetEpisode()));
233  }
234  if (m_parent)
235  {
236  // list is always empty here
237  list.append(lookup);
238  QCoreApplication::postEvent(m_parent,
239  new MetadataLookupFailure(list));
240  }
241  }
242  }
243 
244  RunEpilog();
245 }
246 
248  const QString &originaltitle,
249  bool withArt)
250 {
251  unsigned int exactMatches = 0;
252  unsigned int exactMatchesWithArt = 0;
253 
254  for (const auto& lkup : std::as_const(list))
255  {
256  // Consider exact title matches (ignoring case)
257  if ((QString::compare(lkup->GetTitle(), originaltitle, Qt::CaseInsensitive) == 0))
258  {
259  // In lookup by name, the television database tends to only include Banner artwork.
260  // In lookup by name, the movie database tends to include only Fan and Cover artwork.
261  if ((!(lkup->GetArtwork(kArtworkFanart)).empty()) ||
262  (!(lkup->GetArtwork(kArtworkCoverart)).empty()) ||
263  (!(lkup->GetArtwork(kArtworkBanner)).empty()))
264  {
265  exactMatchesWithArt++;
266  }
267  exactMatches++;
268  }
269  }
270 
271  if (withArt)
272  return exactMatchesWithArt;
273  return exactMatches;
274 }
275 
277  const QString &originaltitle)
278 {
279  QStringList titles;
280  MetadataLookup *ret = nullptr;
281  QDate exactTitleDate;
282  float exactTitlePopularity = 0.0F;
283  int exactMatches = 0;
284  int exactMatchesWithArt = 0;
285  bool foundMatchWithArt = false;
286 
287  // Build a list of all the titles
288  for (const auto& lkup : std::as_const(list))
289  {
290  QString title = lkup->GetTitle();
291  LOG(VB_GENERAL, LOG_INFO, QString("Comparing metadata title '%1' [%2] to recording title '%3'")
292  .arg(title, lkup->GetReleaseDate().toString(), originaltitle));
293  // Consider exact title matches (ignoring case), which have some artwork available.
294  if (QString::compare(title, originaltitle, Qt::CaseInsensitive) == 0)
295  {
296  bool hasArtwork = ((!(lkup->GetArtwork(kArtworkFanart)).empty()) ||
297  (!(lkup->GetArtwork(kArtworkCoverart)).empty()) ||
298  (!(lkup->GetArtwork(kArtworkBanner)).empty()));
299 
300  LOG(VB_GENERAL, LOG_INFO, QString("'%1', popularity = %2, ReleaseDate = %3")
301  .arg(title)
302  .arg(lkup->GetPopularity())
303  .arg(lkup->GetReleaseDate().toString()));
304 
305  // After the first exact match, prefer any more popular one.
306  // Most of the Movie database entries have Popularity fields.
307  // The TV series database generally has no Popularity values specified,
308  // so if none are found so far in the search, pick the most recently
309  // released entry with artwork. Also, if the first exact match had
310  // no artwork, prefer any later exact match with artwork.
311  if ((ret == nullptr) ||
312  (hasArtwork &&
313  ((!foundMatchWithArt) ||
314  ((lkup->GetPopularity() > exactTitlePopularity)) ||
315  ((exactTitlePopularity == 0.0F) && (lkup->GetReleaseDate() > exactTitleDate)))))
316  {
317  exactTitleDate = lkup->GetReleaseDate();
318  exactTitlePopularity = lkup->GetPopularity();
319  ret = lkup;
320  }
321  exactMatches++;
322  if (hasArtwork)
323  {
324  foundMatchWithArt = true;
325  exactMatchesWithArt++;
326  }
327  }
328 
329  titles.append(title);
330  }
331 
332  LOG(VB_GENERAL, LOG_DEBUG, QString("exactMatches = %1, exactMatchesWithArt = %2")
333  .arg(exactMatches)
334  .arg(exactMatchesWithArt));
335 
336  // If there was one or more exact matches then we can skip a more intensive
337  // and time consuming search
338  if (exactMatches > 0)
339  {
340  if (exactMatches == 1)
341  {
342  LOG(VB_GENERAL, LOG_INFO, QString("Single exact title match for '%1'")
343  .arg(originaltitle));
344  }
345  else
346  {
347  LOG(VB_GENERAL, LOG_INFO,
348  QString("Multiple exact title matches found for '%1'. "
349  "Selecting most popular or most recent [%2]")
350  .arg(originaltitle, exactTitleDate.toString()));
351  }
352  return ret;
353  }
354 
355  // Apply Levenshtein distance algorithm to determine closest match
356  QString bestTitle = nearestName(originaltitle, titles);
357 
358  // If no "best" was chosen, give up.
359  if (bestTitle.isEmpty())
360  {
361  LOG(VB_GENERAL, LOG_ERR,
362  QString("No adequate match or multiple "
363  "matches found for %1. Update manually.")
364  .arg(originaltitle));
365  return nullptr;
366  }
367 
368  LOG(VB_GENERAL, LOG_INFO, QString("Best Title Match For %1: %2")
369  .arg(originaltitle, bestTitle));
370 
371  // Grab the one item that matches the besttitle (IMPERFECT)
372  for (const auto& item : std::as_const(list))
373  {
374  if (item->GetTitle() == bestTitle)
375  {
376  ret = item;
377  break;
378  }
379  }
380 
381  return ret;
382 }
383 
384 MetadataLookupList MetadataDownload::runGrabber(const QString& cmd, const QStringList& args,
385  MetadataLookup *lookup,
386  bool passseas)
387 {
388  MythSystemLegacy grabber(cmd, args, kMSStdOut);
389  MetadataLookupList list;
390 
391  LOG(VB_GENERAL, LOG_INFO, QString("Running Grabber: %1 %2")
392  .arg(cmd, args.join(" ")));
393 
394  grabber.Run();
395  grabber.Wait();
396  QByteArray result = grabber.ReadAll();
397  if (!result.isEmpty())
398  {
399  QDomDocument doc;
400  doc.setContent(result, true);
401  QDomElement root = doc.documentElement();
402  QDomElement item = root.firstChildElement("item");
403 
404  while (!item.isNull())
405  {
406  MetadataLookup *tmp = ParseMetadataItem(item, lookup, passseas);
407  list.append(tmp);
408  // MetadataLookup is to be owned by list
409  tmp->DecrRef();
410  item = item.nextSiblingElement("item");
411  }
412  }
413  return list;
414 }
415 
417 {
418  return MetaGrabberScript::GetType(kGrabberMovie).GetPath();
419 }
420 
422 {
424 }
425 
427 {
428  return MetaGrabberScript::GetType(kGrabberGame).GetPath();
429 }
430 
431 bool MetadataDownload::runGrabberTest(const QString &grabberpath)
432 {
433  return MetaGrabberScript(grabberpath).Test();
434 }
435 
437 {
439  {
440  LOG(VB_GENERAL, LOG_INFO,
441  QString("Movie grabber not functional. Aborting this run."));
442  return false;
443  }
444 
445  return true;
446 }
447 
449 {
451  {
452  LOG(VB_GENERAL, LOG_INFO,
453  QString("Television grabber not functional. Aborting this run."));
454  return false;
455  }
456 
457  return true;
458 }
459 
461  MetadataLookup *lookup,
462  bool passseas)
463 {
464  MetadataLookupList list;
465 
466  LOG(VB_GENERAL, LOG_INFO,
467  QString("Matching MXML file found. Parsing %1 for metadata...")
468  .arg(MXMLpath));
469 
470  if (lookup->GetType() == kMetadataVideo)
471  {
472  QByteArray mxmlraw;
473  QDomElement item;
474  auto *rf = new RemoteFile(MXMLpath);
475 
476  if (rf->isOpen())
477  {
478  bool loaded = rf->SaveAs(mxmlraw);
479  if (loaded)
480  {
481  QDomDocument doc;
482  if (doc.setContent(mxmlraw, true))
483  {
484  lookup->SetStep(kLookupData);
485  QDomElement root = doc.documentElement();
486  item = root.firstChildElement("item");
487  }
488  else
489  {
490  LOG(VB_GENERAL, LOG_ERR,
491  QString("Corrupt or invalid MXML file."));
492  }
493  }
494  }
495 
496  delete rf;
497  rf = nullptr;
498 
499  MetadataLookup *tmp = ParseMetadataItem(item, lookup, passseas);
500  list.append(tmp);
501  // MetadataLookup is owned by the MetadataLookupList returned
502  tmp->DecrRef();
503  }
504 
505  return list;
506 }
507 
509  MetadataLookup *lookup)
510 {
511  MetadataLookupList list;
512 
513  LOG(VB_GENERAL, LOG_INFO,
514  QString("Matching NFO file found. Parsing %1 for metadata...")
515  .arg(NFOpath));
516 
517  bool error = false;
518 
519  if (lookup->GetType() == kMetadataVideo)
520  {
521  QByteArray nforaw;
522  QDomElement item;
523  auto *rf = new RemoteFile(NFOpath);
524 
525  if (rf->isOpen())
526  {
527  bool loaded = rf->SaveAs(nforaw);
528 
529  if (loaded)
530  {
531  QDomDocument doc;
532 
533  if (doc.setContent(nforaw, true))
534  {
535  lookup->SetStep(kLookupData);
536  item = doc.documentElement();
537  }
538  else
539  {
540  LOG(VB_GENERAL, LOG_ERR,
541  QString("Invalid NFO file found."));
542  error = true;
543  }
544  }
545  }
546 
547  delete rf;
548  rf = nullptr;
549 
550  if (!error)
551  {
552  MetadataLookup *tmp = ParseMetadataMovieNFO(item, lookup);
553 
554  list.append(tmp);
555  // MetadataLookup is owned by the MetadataLookupList returned
556  tmp->DecrRef();
557  }
558  }
559 
560  return list;
561 }
562 
564 {
565  MetadataLookupList list;
566  MetaGrabberScript grabber =
568  if (!grabber.IsValid())
569  return {};
570 
571  // If the inetref is populated, even in kLookupSearch mode,
572  // become a kLookupData grab and use that.
573  if (lookup->GetStep() == kLookupSearch &&
574  (!lookup->GetInetref().isEmpty() &&
575  lookup->GetInetref() != "00000000"))
576  {
577  lookup->SetStep(kLookupData);
578  }
579 
580  if (lookup->GetStep() == kLookupSearch)
581  {
582  if (lookup->GetTitle().isEmpty())
583  {
584  // no point searching on nothing...
585  return list;
586  }
587  // we're searching
588  list = grabber.Search(lookup->GetTitle(), lookup);
589  }
590  else if (lookup->GetStep() == kLookupData)
591  {
592  // we're just grabbing data
593  list = grabber.LookupData(lookup->GetInetref(), lookup);
594  }
595 
596  return list;
597 }
598 
608 {
609  MetadataLookupList list;
610 
611  MetaGrabberScript grabber =
613  if (!grabber.IsValid())
614  return {};
615 
616  // initial search mode
617  if (!lookup->GetInetref().isEmpty() && lookup->GetInetref() != "00000000" &&
618  (lookup->GetStep() == kLookupSearch || lookup->GetStep() == kLookupData))
619  {
620  // with inetref
621  lookup->SetStep(kLookupData);
622  // we're just grabbing data
623  list = grabber.LookupData(lookup->GetInetref(), lookup);
624  }
625  else if (lookup->GetStep() == kLookupSearch)
626  {
627  if (lookup->GetBaseTitle().isEmpty())
628  {
629  // no point searching on nothing...
630  return list;
631  }
632  list = grabber.Search(lookup->GetBaseTitle(), lookup);
633  }
634 
635  return list;
636 }
637 
650 {
651  MetadataLookupList list;
652 
653  MetaGrabberScript grabber =
655  if (!grabber.IsValid())
656  return {};
657  bool searchcollection = false;
658 
659  // initial search mode
660  if (!lookup->GetInetref().isEmpty() && lookup->GetInetref() != "00000000" &&
661  (lookup->GetStep() == kLookupSearch || lookup->GetStep() == kLookupData))
662  {
663  // with inetref
664  lookup->SetStep(kLookupData);
665  if (lookup->GetSeason() || lookup->GetEpisode())
666  {
667  list = grabber.LookupData(lookup->GetInetref(), lookup->GetSeason(),
668  lookup->GetEpisode(), lookup);
669  }
670 
671  if (list.isEmpty() && (!lookup->GetSubtitle().isEmpty()))
672  {
673  list = grabber.SearchSubtitle(lookup->GetInetref(),
674  lookup->GetBaseTitle() /* unused */,
675  lookup->GetSubtitle(), lookup, false);
676  }
677 
678  if (list.isEmpty() && !lookup->GetCollectionref().isEmpty())
679  {
680  list = grabber.LookupCollection(lookup->GetCollectionref(), lookup);
681  searchcollection = true;
682  }
683  else if (list.isEmpty())
684  {
685  // We do not store CollectionRef in our database
686  // so try with the inetref, for all purposes with TVDB, they are
687  // always identical
688  list = grabber.LookupCollection(lookup->GetInetref(), lookup);
689  searchcollection = true;
690  }
691  }
692  else if (lookup->GetStep() == kLookupSearch)
693  {
694  if (lookup->GetBaseTitle().isEmpty())
695  {
696  // no point searching on nothing...
697  return list;
698  }
699  if (!lookup->GetSubtitle().isEmpty())
700  {
701  list = grabber.SearchSubtitle(lookup->GetBaseTitle(),
702  lookup->GetSubtitle(), lookup, false);
703  }
704  if (list.isEmpty())
705  {
706  list = grabber.Search(lookup->GetBaseTitle(), lookup);
707  }
708  }
709  else if (lookup->GetStep() == kLookupCollection)
710  {
711  list = grabber.LookupCollection(lookup->GetCollectionref(), lookup);
712  }
713 
714  // Collection Fallback
715  // If the lookup allows generic metadata, and the specific
716  // season and episode are not available, try for series metadata.
717  if (!searchcollection && list.isEmpty() &&
718  !lookup->GetCollectionref().isEmpty() &&
719  lookup->GetAllowGeneric() && lookup->GetStep() == kLookupData)
720  {
721  lookup->SetStep(kLookupCollection);
722  list = grabber.LookupCollection(lookup->GetCollectionref(), lookup);
723  }
724 
725  if (!list.isEmpty())
726  {
727  // mark all results so that search collection is properly handled later
728  lookup->SetIsCollection(searchcollection);
729  // NOLINTNEXTLINE(modernize-loop-convert)
730  for (auto it = list.begin(); it != list.end(); ++it)
731  {
732  (*it)->SetIsCollection(searchcollection);
733  }
734  }
735 
736  return list;
737 }
738 
740 {
741  MetadataLookupList list;
742 
743  if (lookup->GetSubtype() != kProbableMovie &&
744  !lookup->GetSubtitle().isEmpty())
745  {
746  list.append(handleTelevision(lookup));
747  }
748 
749  if (lookup->GetSubtype() != kProbableTelevision)
750  {
751  list.append(handleMovie(lookup));
752  }
753 
754  if (list.count() == 1)
755  {
756  list[0]->SetStep(kLookupData);
757  }
758 
759  return list;
760 }
761 
763 {
764  // We only enter this mode if we are pretty darn sure this is a TV show,
765  // but we're for some reason looking up a generic, or the title didn't
766  // exactly match in one of the earlier lookups. This is a total
767  // hail mary to try to get at least *series* level info and art/inetref.
768 
769  MetadataLookupList list;
770 
771  if (lookup->GetBaseTitle().isEmpty())
772  {
773  // no point searching on nothing...
774  return list;
775  }
776 
777  // no inetref known, just pull the default grabber
779 
780  // cache some initial values so we can change them in the lookup later
781  LookupType origtype = lookup->GetSubtype();
782  int origseason = lookup->GetSeason();
783  int origepisode = lookup->GetEpisode();
784 
785  if (origseason == 0 && origepisode == 0)
786  {
787  lookup->SetSeason(1);
788  lookup->SetEpisode(1);
789  }
790 
791  list = grabber.Search(lookup->GetBaseTitle(), lookup);
792 
793  if (list.count() == 1)
794  {
795  // search was successful, rerun as normal television mode
796  lookup->SetInetref(list[0]->GetInetref());
797  lookup->SetCollectionref(list[0]->GetCollectionref());
798  list = handleTelevision(lookup);
799  }
800 
801  lookup->SetSeason(origseason);
802  lookup->SetEpisode(origepisode);
803  lookup->SetSubtype(origtype);
804 
805  return list;
806 }
807 
808 static QString getNameWithExtension(const QString &filename, const QString &type)
809 {
810  QString ret;
811  QString newname;
812  QUrl qurl(filename);
813  QString ext = QFileInfo(qurl.path()).suffix();
814 
815  if (ext.isEmpty())
816  {
817  // no extension, assume it is a directory
818  newname = filename + "/" + QFileInfo(qurl.path()).fileName() + "." + type;
819  }
820  else
821  {
822  newname = filename.left(filename.size() - ext.size()) + type;
823  }
824 
825  if (RemoteFile::Exists(newname))
826  ret = newname;
827 
828  return ret;
829 }
830 
832 {
833  return getNameWithExtension(filename, "mxml");
834 }
835 
836 QString MetadataDownload::getNFOPath(const QString& filename)
837 {
838  return getNameWithExtension(filename, "nfo");
839 }
MetadataDownload::readMXML
static MetadataLookupList readMXML(const QString &MXMLpath, MetadataLookup *lookup, bool passseas=true)
Definition: metadatadownload.cpp:460
MetadataDownload::runGrabberTest
static bool runGrabberTest(const QString &grabberpath)
Definition: metadatadownload.cpp:431
MetadataDownload::m_lookupList
MetadataLookupList m_lookupList
Definition: metadatadownload.h:87
build_compdb.args
args
Definition: build_compdb.py:11
MetaGrabberScript
Definition: metadatagrabber.h:29
MetadataDownload::run
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: metadatadownload.cpp:73
MetaGrabberScript::LookupCollection
MetadataLookupList LookupCollection(const QString &collectionref, MetadataLookup *lookup, bool passseas=true)
Definition: metadatagrabber.cpp:522
MetadataDownload::runGrabber
static MetadataLookupList runGrabber(const QString &cmd, const QStringList &args, MetadataLookup *lookup, bool passseas=true)
Definition: metadatadownload.cpp:384
RefCountHandler
Definition: referencecounterlist.h:17
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
kGrabberTelevision
@ kGrabberTelevision
Definition: metadatagrabber.h:23
MetadataDownload::findBestMatch
static MetadataLookup * findBestMatch(MetadataLookupList list, const QString &originaltitle)
Definition: metadatadownload.cpp:276
MetadataLookup::SetSubtype
void SetSubtype(LookupType subtype)
Definition: metadatacommon.h:240
error
static void error(const char *str,...)
Definition: vbi.cpp:36
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
MetadataLookup::SetIsCollection
void SetIsCollection(bool collection)
Definition: metadatacommon.h:273
kMetadataRecording
@ kMetadataRecording
Definition: metadatacommon.h:44
MythSystemLegacy
Definition: mythsystemlegacy.h:67
MetadataLookup::GetTitle
QString GetTitle() const
Definition: metadatacommon.h:299
MetaGrabberScript::Test
bool Test(void)
Definition: metadatagrabber.cpp:370
MetaGrabberScript::SearchSubtitle
MetadataLookupList SearchSubtitle(const QString &title, const QString &subtitle, MetadataLookup *lookup, bool passseas=true)
Definition: metadatagrabber.cpp:466
kMetadataVideo
@ kMetadataVideo
Definition: metadatacommon.h:43
RemoteFile::Exists
static bool Exists(const QString &url, struct stat *fileinfo)
Definition: remotefile.cpp:454
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
MetadataLookup::GetSubtype
LookupType GetSubtype() const
Definition: metadatacommon.h:287
RefCountedList::takeFirstAndDecr
RefCountHandler< T > takeFirstAndDecr(void)
Removes the first item in the list and returns it.
Definition: referencecounterlist.h:112
MetadataDownload::prependLookup
void prependLookup(MetadataLookup *lookup)
prependLookup: Add lookup to top of the queue MetadataDownload::m_lookupList takes ownership of the g...
Definition: metadatadownload.cpp:54
kProbableTelevision
@ kProbableTelevision
Definition: metadatacommon.h:51
RemoteFile
Definition: remotefile.h:17
GuessLookupType
LookupType GuessLookupType(ProgramInfo *pginfo)
Definition: metadatafactory.cpp:646
MetaGrabberScript::IsValid
bool IsValid(void) const
Definition: metadatagrabber.h:55
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
MythSystemLegacy::ReadAll
QByteArray & ReadAll()
Definition: mythsystemlegacy.cpp:402
MetadataDownload::GetTelevisionGrabber
static QString GetTelevisionGrabber()
Definition: metadatadownload.cpp:421
mythdirs.h
MetadataDownload::~MetadataDownload
~MetadataDownload() override
Definition: metadatadownload.cpp:29
MetadataLookup::SetCollectionref
void SetCollectionref(const QString &collectionref)
Definition: metadatacommon.h:270
kLookupSearch
@ kLookupSearch
Definition: metadatacommon.h:28
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
MetadataLookup::GetStep
LookupStep GetStep() const
Definition: metadatacommon.h:289
kGrabberMovie
@ kGrabberMovie
Definition: metadatagrabber.h:22
nearestName
QString nearestName(const QString &actual, const QStringList &candidates)
Definition: metadatacommon.cpp:1387
mythsystemlegacy.h
MetadataDownload::handleMovie
static MetadataLookupList handleMovie(MetadataLookup *lookup)
handleMovie: attempt to find movie data via the following (in order) 1- Local MXML: already done befo...
Definition: metadatadownload.cpp:607
MetadataLookup
Definition: metadatacommon.h:87
MetadataDownload::getNFOPath
static QString getNFOPath(const QString &filename)
Definition: metadatadownload.cpp:836
MetadataLookup::SetEpisode
void SetEpisode(uint episode)
Definition: metadatacommon.h:268
MetaGrabberScript::Search
MetadataLookupList Search(const QString &title, MetadataLookup *lookup, bool passseas=true)
Definition: metadatagrabber.cpp:454
mythlogging.h
MetadataLookup::GetEpisode
uint GetEpisode() const
Definition: metadatacommon.h:315
MetadataLookupFailure
Definition: metadatadownload.h:23
remotefile.h
metadatadownload.h
RefCountedList< MetadataLookup >
MetadataDownload::m_parent
QObject * m_parent
Definition: metadatadownload.h:86
kLookupData
@ kLookupData
Definition: metadatacommon.h:29
getNameWithExtension
static QString getNameWithExtension(const QString &filename, const QString &type)
Definition: metadatadownload.cpp:808
MetadataLookup::GetType
MetadataType GetType() const
Definition: metadatacommon.h:286
MythSystemLegacy::Wait
uint Wait(std::chrono::seconds timeout=0s)
Definition: mythsystemlegacy.cpp:243
kArtworkFanart
@ kArtworkFanart
Definition: metadataimagehelper.h:12
MetadataLookup::GetSubtitle
QString GetSubtitle() const
Definition: metadatacommon.h:310
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
MetadataDownload::readNFO
static MetadataLookupList readNFO(const QString &NFOpath, MetadataLookup *lookup)
Definition: metadatadownload.cpp:508
storagegroup.h
kLookupCollection
@ kLookupCollection
Definition: metadatacommon.h:30
MetadataDownload::addLookup
void addLookup(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_lookupList takes ownership of the gi...
Definition: metadatadownload.cpp:39
MetadataDownload::handleRecordingGeneric
static MetadataLookupList handleRecordingGeneric(MetadataLookup *lookup)
Definition: metadatadownload.cpp:762
MetadataLookup::GetCollectionref
QString GetCollectionref() const
Definition: metadatacommon.h:357
RefCountedList::takeFirst
T * takeFirst(void)
Removes the first item in the list and returns it.
Definition: referencecounterlist.h:78
MetadataLookup::SetSeason
void SetSeason(uint season)
Definition: metadatacommon.h:267
MetadataDownload::handleTelevision
static MetadataLookupList handleTelevision(MetadataLookup *lookup)
handleTelevision attempt to find television data via the following (in order) 1- Local MXML: already ...
Definition: metadatadownload.cpp:649
MetaGrabberScript::GetGrabber
static MetaGrabberScript GetGrabber(GrabberType defaultType, const MetadataLookup *lookup=nullptr)
Definition: metadatagrabber.cpp:143
MetadataLookup::GetAllowGeneric
bool GetAllowGeneric() const
Definition: metadatacommon.h:295
MetadataLookupFailure::kEventType
static const Type kEventType
Definition: metadatadownload.h:32
MetadataLookup::GetSeason
uint GetSeason() const
Definition: metadatacommon.h:314
MetadataLookup::GetFilename
QString GetFilename() const
Definition: metadatacommon.h:298
kUnknownVideo
@ kUnknownVideo
Definition: metadatacommon.h:54
MetadataLookup::GetBaseTitle
QString GetBaseTitle() const
Definition: metadatacommon.h:300
mythuihelper.h
MetadataDownload::handleGame
static MetadataLookupList handleGame(MetadataLookup *lookup)
Definition: metadatadownload.cpp:563
MetadataDownload::getMXMLPath
static QString getMXMLPath(const QString &filename)
Definition: metadatadownload.cpp:831
mythmiscutil.h
MetadataDownload::MovieGrabberWorks
static bool MovieGrabberWorks()
Definition: metadatadownload.cpp:436
mythcorecontext.h
MetadataLookup::SetAutomatic
void SetAutomatic(bool autom)
Definition: metadatacommon.h:246
kGrabberGame
@ kGrabberGame
Definition: metadatagrabber.h:25
MetadataLookup::GetInetref
QString GetInetref() const
Definition: metadatacommon.h:356
MetadataLookup::SetInetref
void SetInetref(const QString &inetref)
Definition: metadatacommon.h:269
MetaGrabberScript::LookupData
MetadataLookupList LookupData(const QString &inetref, MetadataLookup *lookup, bool passseas=true)
Definition: metadatagrabber.cpp:495
MetadataDownload::handleVideoUndetermined
static MetadataLookupList handleVideoUndetermined(MetadataLookup *lookup)
Definition: metadatadownload.cpp:739
kMetadataGame
@ kMetadataGame
Definition: metadatacommon.h:46
LookupType
LookupType
Definition: metadatacommon.h:50
MetaGrabberScript::GetType
GrabberType GetType(void) const
Definition: metadatagrabber.h:64
metadatafactory.h
MThread::isRunning
bool isRunning(void) const
Definition: mthread.cpp:263
kArtworkBanner
@ kArtworkBanner
Definition: metadataimagehelper.h:13
MetadataDownload::m_mutex
QMutex m_mutex
Definition: metadatadownload.h:88
ParseMetadataItem
MetadataLookup * ParseMetadataItem(const QDomElement &item, MetadataLookup *lookup, bool passseas)
Definition: metadatacommon.cpp:894
MetadataLookupEvent::kEventType
static const Type kEventType
Definition: metadatadownload.h:20
MythSystemLegacy::Run
void Run(std::chrono::seconds timeout=0s)
Runs a command inside the /bin/sh shell. Returns immediately.
Definition: mythsystemlegacy.cpp:213
MetadataLookup::GetAutomatic
bool GetAutomatic() const
Definition: metadatacommon.h:290
MetadataDownload::GetGameGrabber
static QString GetGameGrabber()
Definition: metadatadownload.cpp:426
ParseMetadataMovieNFO
MetadataLookup * ParseMetadataMovieNFO(const QDomElement &item, MetadataLookup *lookup)
Definition: metadatacommon.cpp:1153
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:101
build_compdb.filename
filename
Definition: build_compdb.py:21
kProbableMovie
@ kProbableMovie
Definition: metadatacommon.h:53
MetadataLookupEvent
Definition: metadatadownload.h:11
kMSStdOut
@ kMSStdOut
allow access to stdout
Definition: mythsystem.h:41
kArtworkCoverart
@ kArtworkCoverart
Definition: metadataimagehelper.h:11
MetadataDownload::GetMovieGrabber
static QString GetMovieGrabber()
Definition: metadatadownload.cpp:416
MetadataDownload::TelevisionGrabberWorks
static bool TelevisionGrabberWorks()
Definition: metadatadownload.cpp:448
MetadataLookup::SetStep
void SetStep(LookupStep step)
Definition: metadatacommon.h:244
MetadataLookupList
RefCountedList< MetadataLookup > MetadataLookupList
Definition: metadatacommon.h:462
MetadataDownload::cancel
void cancel()
Definition: metadatadownload.cpp:65
MetadataDownload::findExactMatchCount
static unsigned int findExactMatchCount(MetadataLookupList list, const QString &originaltitle, bool withArt)
Definition: metadatadownload.cpp:247