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 
24  (QEvent::Type) QEvent::registerEventType();
25 
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 : qAsConst(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 : qAsConst(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 : qAsConst(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 
569  // If the inetref is populated, even in kLookupSearch mode,
570  // become a kLookupData grab and use that.
571  if (lookup->GetStep() == kLookupSearch &&
572  (!lookup->GetInetref().isEmpty() &&
573  lookup->GetInetref() != "00000000"))
574  {
575  lookup->SetStep(kLookupData);
576  }
577 
578  if (lookup->GetStep() == kLookupSearch)
579  {
580  if (lookup->GetTitle().isEmpty())
581  {
582  // no point searching on nothing...
583  return list;
584  }
585  // we're searching
586  list = grabber.Search(lookup->GetTitle(), lookup);
587  }
588  else if (lookup->GetStep() == kLookupData)
589  {
590  // we're just grabbing data
591  list = grabber.LookupData(lookup->GetInetref(), lookup);
592  }
593 
594  return list;
595 }
596 
606 {
607  MetadataLookupList list;
608 
609  MetaGrabberScript grabber =
611 
612  // initial search mode
613  if (!lookup->GetInetref().isEmpty() && lookup->GetInetref() != "00000000" &&
614  (lookup->GetStep() == kLookupSearch || lookup->GetStep() == kLookupData))
615  {
616  // with inetref
617  lookup->SetStep(kLookupData);
618  // we're just grabbing data
619  list = grabber.LookupData(lookup->GetInetref(), lookup);
620  }
621  else if (lookup->GetStep() == kLookupSearch)
622  {
623  if (lookup->GetBaseTitle().isEmpty())
624  {
625  // no point searching on nothing...
626  return list;
627  }
628  list = grabber.Search(lookup->GetBaseTitle(), lookup);
629  }
630 
631  return list;
632 }
633 
646 {
647  MetadataLookupList list;
648 
649  MetaGrabberScript grabber =
651  bool searchcollection = false;
652 
653  // initial search mode
654  if (!lookup->GetInetref().isEmpty() && lookup->GetInetref() != "00000000" &&
655  (lookup->GetStep() == kLookupSearch || lookup->GetStep() == kLookupData))
656  {
657  // with inetref
658  lookup->SetStep(kLookupData);
659  if (lookup->GetSeason() || lookup->GetEpisode())
660  {
661  list = grabber.LookupData(lookup->GetInetref(), lookup->GetSeason(),
662  lookup->GetEpisode(), lookup);
663  }
664 
665  if (list.isEmpty() && (!lookup->GetSubtitle().isEmpty()))
666  {
667  list = grabber.SearchSubtitle(lookup->GetInetref(),
668  lookup->GetBaseTitle() /* unused */,
669  lookup->GetSubtitle(), lookup, false);
670  }
671 
672  if (list.isEmpty() && !lookup->GetCollectionref().isEmpty())
673  {
674  list = grabber.LookupCollection(lookup->GetCollectionref(), lookup);
675  searchcollection = true;
676  }
677  else if (list.isEmpty())
678  {
679  // We do not store CollectionRef in our database
680  // so try with the inetref, for all purposes with TVDB, they are
681  // always identical
682  list = grabber.LookupCollection(lookup->GetInetref(), lookup);
683  searchcollection = true;
684  }
685  }
686  else if (lookup->GetStep() == kLookupSearch)
687  {
688  if (lookup->GetBaseTitle().isEmpty())
689  {
690  // no point searching on nothing...
691  return list;
692  }
693  if (!lookup->GetSubtitle().isEmpty())
694  {
695  list = grabber.SearchSubtitle(lookup->GetBaseTitle(),
696  lookup->GetSubtitle(), lookup, false);
697  }
698  if (list.isEmpty())
699  {
700  list = grabber.Search(lookup->GetBaseTitle(), lookup);
701  }
702  }
703  else if (lookup->GetStep() == kLookupCollection)
704  {
705  list = grabber.LookupCollection(lookup->GetCollectionref(), lookup);
706  }
707 
708  // Collection Fallback
709  // If the lookup allows generic metadata, and the specific
710  // season and episode are not available, try for series metadata.
711  if (!searchcollection && list.isEmpty() &&
712  !lookup->GetCollectionref().isEmpty() &&
713  lookup->GetAllowGeneric() && lookup->GetStep() == kLookupData)
714  {
715  lookup->SetStep(kLookupCollection);
716  list = grabber.LookupCollection(lookup->GetCollectionref(), lookup);
717  }
718 
719  if (!list.isEmpty())
720  {
721  // mark all results so that search collection is properly handled later
722  lookup->SetIsCollection(searchcollection);
723  // NOLINTNEXTLINE(modernize-loop-convert)
724  for (auto it = list.begin(); it != list.end(); ++it)
725  {
726  (*it)->SetIsCollection(searchcollection);
727  }
728  }
729 
730  return list;
731 }
732 
734 {
735  MetadataLookupList list;
736 
737  if (lookup->GetSubtype() != kProbableMovie &&
738  !lookup->GetSubtitle().isEmpty())
739  {
740  list.append(handleTelevision(lookup));
741  }
742 
743  if (lookup->GetSubtype() != kProbableTelevision)
744  {
745  list.append(handleMovie(lookup));
746  }
747 
748  if (list.count() == 1)
749  {
750  list[0]->SetStep(kLookupData);
751  }
752 
753  return list;
754 }
755 
757 {
758  // We only enter this mode if we are pretty darn sure this is a TV show,
759  // but we're for some reason looking up a generic, or the title didn't
760  // exactly match in one of the earlier lookups. This is a total
761  // hail mary to try to get at least *series* level info and art/inetref.
762 
763  MetadataLookupList list;
764 
765  if (lookup->GetBaseTitle().isEmpty())
766  {
767  // no point searching on nothing...
768  return list;
769  }
770 
771  // no inetref known, just pull the default grabber
773 
774  // cache some initial values so we can change them in the lookup later
775  LookupType origtype = lookup->GetSubtype();
776  int origseason = lookup->GetSeason();
777  int origepisode = lookup->GetEpisode();
778 
779  if (origseason == 0 && origepisode == 0)
780  {
781  lookup->SetSeason(1);
782  lookup->SetEpisode(1);
783  }
784 
785  list = grabber.Search(lookup->GetBaseTitle(), lookup);
786 
787  if (list.count() == 1)
788  {
789  // search was successful, rerun as normal television mode
790  lookup->SetInetref(list[0]->GetInetref());
791  lookup->SetCollectionref(list[0]->GetCollectionref());
792  list = handleTelevision(lookup);
793  }
794 
795  lookup->SetSeason(origseason);
796  lookup->SetEpisode(origepisode);
797  lookup->SetSubtype(origtype);
798 
799  return list;
800 }
801 
802 static QString getNameWithExtension(const QString &filename, const QString &type)
803 {
804  QString ret;
805  QString newname;
806  QUrl qurl(filename);
807  QString ext = QFileInfo(qurl.path()).suffix();
808 
809  if (ext.isEmpty())
810  {
811  // no extension, assume it is a directory
812  newname = filename + "/" + QFileInfo(qurl.path()).fileName() + "." + type;
813  }
814  else
815  {
816  newname = filename.left(filename.size() - ext.size()) + type;
817  }
818 
819  if (RemoteFile::Exists(newname))
820  ret = newname;
821 
822  return ret;
823 }
824 
826 {
827  return getNameWithExtension(filename, "mxml");
828 }
829 
830 QString MetadataDownload::getNFOPath(const QString& filename)
831 {
832  return getNameWithExtension(filename, "nfo");
833 }
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:507
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:355
MetaGrabberScript::SearchSubtitle
MetadataLookupList SearchSubtitle(const QString &title, const QString &subtitle, MetadataLookup *lookup, bool passseas=true)
Definition: metadatagrabber.cpp:451
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
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:1386
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:605
MetadataLookup
Definition: metadatacommon.h:87
MetadataLookupFailure::kEventType
static Type kEventType
Definition: metadatadownload.h:32
MetadataDownload::getNFOPath
static QString getNFOPath(const QString &filename)
Definition: metadatadownload.cpp:830
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:439
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:802
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:756
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:645
MetaGrabberScript::GetGrabber
static MetaGrabberScript GetGrabber(GrabberType defaultType, const MetadataLookup *lookup=nullptr)
Definition: metadatagrabber.cpp:130
MetadataLookup::GetAllowGeneric
bool GetAllowGeneric() const
Definition: metadatacommon.h:295
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:825
MetadataLookupEvent::kEventType
static Type kEventType
Definition: metadatadownload.h:20
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:480
MetadataDownload::handleVideoUndetermined
static MetadataLookupList handleVideoUndetermined(MetadataLookup *lookup)
Definition: metadatadownload.cpp:733
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:893
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:1152
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