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