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