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)
292  .arg(lkup->GetReleaseDate().toString())
293  .arg(originaltitle));
294  // Consider exact title matches (ignoring case), which have some artwork available.
295  if (QString::compare(title, originaltitle, Qt::CaseInsensitive) == 0)
296  {
297  bool hasArtwork = ((!(lkup->GetArtwork(kArtworkFanart)).empty()) ||
298  (!(lkup->GetArtwork(kArtworkCoverart)).empty()) ||
299  (!(lkup->GetArtwork(kArtworkBanner)).empty()));
300 
301  LOG(VB_GENERAL, LOG_INFO, QString("'%1', popularity = %2, ReleaseDate = %3")
302  .arg(title)
303  .arg(lkup->GetPopularity())
304  .arg(lkup->GetReleaseDate().toString()));
305 
306  // After the first exact match, prefer any more popular one.
307  // Most of the Movie database entries have Popularity fields.
308  // The TV series database generally has no Popularity values specified,
309  // so if none are found so far in the search, pick the most recently
310  // released entry with artwork. Also, if the first exact match had
311  // no artwork, prefer any later exact match with artwork.
312  if ((ret == nullptr) ||
313  (hasArtwork &&
314  ((!foundMatchWithArt) ||
315  ((lkup->GetPopularity() > exactTitlePopularity)) ||
316  ((exactTitlePopularity == 0.0F) && (lkup->GetReleaseDate() > exactTitleDate)))))
317  {
318  exactTitleDate = lkup->GetReleaseDate();
319  exactTitlePopularity = lkup->GetPopularity();
320  ret = lkup;
321  }
322  exactMatches++;
323  if (hasArtwork)
324  {
325  foundMatchWithArt = true;
326  exactMatchesWithArt++;
327  }
328  }
329 
330  titles.append(title);
331  }
332 
333  LOG(VB_GENERAL, LOG_DEBUG, QString("exactMatches = %1, exactMatchesWithArt = %2")
334  .arg(exactMatches)
335  .arg(exactMatchesWithArt));
336 
337  // If there was one or more exact matches then we can skip a more intensive
338  // and time consuming search
339  if (exactMatches > 0)
340  {
341  if (exactMatches == 1)
342  {
343  LOG(VB_GENERAL, LOG_INFO, QString("Single exact title match for '%1'")
344  .arg(originaltitle));
345  }
346  else
347  {
348  LOG(VB_GENERAL, LOG_INFO,
349  QString("Multiple exact title matches found for '%1'. "
350  "Selecting most popular or most recent [%2]")
351  .arg(originaltitle)
352  .arg(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).arg(bestTitle));
372 
373  // Grab the one item that matches the besttitle (IMPERFECT)
374  for (auto item : qAsConst(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).arg(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 
571  // If the inetref is populated, even in kLookupSearch mode,
572  // become a kLookupData grab and use that.
573  if (lookup->GetStep() == kLookupSearch &&
574  (!lookup->GetInetref().isEmpty() &&
575  lookup->GetInetref() != "00000000"))
576  {
577  lookup->SetStep(kLookupData);
578  }
579 
580  if (lookup->GetStep() == kLookupSearch)
581  {
582  if (lookup->GetTitle().isEmpty())
583  {
584  // no point searching on nothing...
585  return list;
586  }
587  // we're searching
588  list = grabber.Search(lookup->GetTitle(), lookup);
589  }
590  else if (lookup->GetStep() == kLookupData)
591  {
592  // we're just grabbing data
593  list = grabber.LookupData(lookup->GetInetref(), lookup);
594  }
595 
596  return list;
597 }
598 
608 {
609  MetadataLookupList list;
610 
611  MetaGrabberScript grabber =
613 
614  // initial search mode
615  if (!lookup->GetInetref().isEmpty() && lookup->GetInetref() != "00000000" &&
616  (lookup->GetStep() == kLookupSearch || lookup->GetStep() == kLookupData))
617  {
618  // with inetref
619  lookup->SetStep(kLookupData);
620  // we're just grabbing data
621  list = grabber.LookupData(lookup->GetInetref(), lookup);
622  }
623  else if (lookup->GetStep() == kLookupSearch)
624  {
625  if (lookup->GetBaseTitle().isEmpty())
626  {
627  // no point searching on nothing...
628  return list;
629  }
630  list = grabber.Search(lookup->GetBaseTitle(), lookup);
631  }
632 
633  return list;
634 }
635 
648 {
649  MetadataLookupList list;
650 
651  MetaGrabberScript grabber =
653  bool searchcollection = false;
654 
655  // initial search mode
656  if (!lookup->GetInetref().isEmpty() && lookup->GetInetref() != "00000000" &&
657  (lookup->GetStep() == kLookupSearch || lookup->GetStep() == kLookupData))
658  {
659  // with inetref
660  lookup->SetStep(kLookupData);
661  if (!lookup->GetSubtitle().isEmpty())
662  {
663  list = grabber.SearchSubtitle(lookup->GetInetref(),
664  lookup->GetBaseTitle() /* unused */,
665  lookup->GetSubtitle(), lookup, false);
666  }
667 
668  if (list.isEmpty() && (lookup->GetSeason() || lookup->GetEpisode()))
669  {
670  list = grabber.LookupData(lookup->GetInetref(), lookup->GetSeason(),
671  lookup->GetEpisode(), lookup);
672  }
673 
674  if (list.isEmpty() && !lookup->GetCollectionref().isEmpty())
675  {
676  list = grabber.LookupCollection(lookup->GetCollectionref(), lookup);
677  searchcollection = true;
678  }
679  else if (list.isEmpty())
680  {
681  // We do not store CollectionRef in our database
682  // so try with the inetref, for all purposes with TVDB, they are
683  // always identical
684  list = grabber.LookupCollection(lookup->GetInetref(), lookup);
685  searchcollection = true;
686  }
687  }
688  else if (lookup->GetStep() == kLookupSearch)
689  {
690  if (lookup->GetBaseTitle().isEmpty())
691  {
692  // no point searching on nothing...
693  return list;
694  }
695  if (!lookup->GetSubtitle().isEmpty())
696  {
697  list = grabber.SearchSubtitle(lookup->GetBaseTitle(),
698  lookup->GetSubtitle(), lookup, false);
699  }
700  if (list.isEmpty())
701  {
702  list = grabber.Search(lookup->GetBaseTitle(), lookup);
703  }
704  }
705  else if (lookup->GetStep() == kLookupCollection)
706  {
707  list = grabber.LookupCollection(lookup->GetCollectionref(), lookup);
708  }
709 
710  // Collection Fallback
711  // If the lookup allows generic metadata, and the specific
712  // season and episode are not available, try for series metadata.
713  if (!searchcollection && list.isEmpty() &&
714  !lookup->GetCollectionref().isEmpty() &&
715  lookup->GetAllowGeneric() && lookup->GetStep() == kLookupData)
716  {
717  lookup->SetStep(kLookupCollection);
718  list = grabber.LookupCollection(lookup->GetCollectionref(), lookup);
719  }
720 
721  if (!list.isEmpty())
722  {
723  // mark all results so that search collection is properly handled later
724  lookup->SetIsCollection(searchcollection);
725  // NOLINTNEXTLINE(modernize-loop-convert)
726  for (auto it = list.begin(); it != list.end(); ++it)
727  {
728  (*it)->SetIsCollection(searchcollection);
729  }
730  }
731 
732  return list;
733 }
734 
736 {
737  MetadataLookupList list;
738 
739  if (lookup->GetSubtype() != kProbableMovie &&
740  !lookup->GetSubtitle().isEmpty())
741  {
742  list.append(handleTelevision(lookup));
743  }
744 
745  if (lookup->GetSubtype() != kProbableTelevision)
746  {
747  list.append(handleMovie(lookup));
748  }
749 
750  if (list.count() == 1)
751  {
752  list[0]->SetStep(kLookupData);
753  }
754 
755  return list;
756 }
757 
759 {
760  // We only enter this mode if we are pretty darn sure this is a TV show,
761  // but we're for some reason looking up a generic, or the title didn't
762  // exactly match in one of the earlier lookups. This is a total
763  // hail mary to try to get at least *series* level info and art/inetref.
764 
765  MetadataLookupList list;
766 
767  if (lookup->GetBaseTitle().isEmpty())
768  {
769  // no point searching on nothing...
770  return list;
771  }
772 
773  // no inetref known, just pull the default grabber
775 
776  // cache some initial values so we can change them in the lookup later
777  LookupType origtype = lookup->GetSubtype();
778  int origseason = lookup->GetSeason();
779  int origepisode = lookup->GetEpisode();
780 
781  if (origseason == 0 && origepisode == 0)
782  {
783  lookup->SetSeason(1);
784  lookup->SetEpisode(1);
785  }
786 
787  list = grabber.Search(lookup->GetBaseTitle(), lookup);
788 
789  if (list.count() == 1)
790  {
791  // search was successful, rerun as normal television mode
792  lookup->SetInetref(list[0]->GetInetref());
793  lookup->SetCollectionref(list[0]->GetCollectionref());
794  list = handleTelevision(lookup);
795  }
796 
797  lookup->SetSeason(origseason);
798  lookup->SetEpisode(origepisode);
799  lookup->SetSubtype(origtype);
800 
801  return list;
802 }
803 
804 static QString getNameWithExtension(const QString &filename, const QString &type)
805 {
806  QString ret;
807  QString newname;
808  QUrl qurl(filename);
809  QString ext = QFileInfo(qurl.path()).suffix();
810 
811  if (ext.isEmpty())
812  {
813  // no extension, assume it is a directory
814  newname = filename + "/" + QFileInfo(qurl.path()).fileName() + "." + type;
815  }
816  else
817  {
818  newname = filename.left(filename.size() - ext.size()) + type;
819  }
820 
821  if (RemoteFile::Exists(newname))
822  ret = newname;
823 
824  return ret;
825 }
826 
828 {
829  return getNameWithExtension(filename, "mxml");
830 }
831 
832 QString MetadataDownload::getNFOPath(const QString& filename)
833 {
834  return getNameWithExtension(filename, "nfo");
835 }
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:30
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:517
MetadataDownload::runGrabber
static MetadataLookupList runGrabber(const QString &cmd, const QStringList &args, MetadataLookup *lookup, bool passseas=true)
Definition: metadatadownload.cpp:386
RefCountHandler
Definition: referencecounterlist.h:18
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:288
kGrabberTelevision
@ kGrabberTelevision
Definition: metadatagrabber.h:23
MetadataDownload::findBestMatch
static MetadataLookup * findBestMatch(MetadataLookupList list, const QString &originaltitle)
Definition: metadatadownload.cpp:275
root
QDomElement root
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:656
MetadataLookup::SetSubtype
void SetSubtype(LookupType subtype)
Definition: metadatacommon.h:239
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:272
kMetadataRecording
@ kMetadataRecording
Definition: metadatacommon.h:43
MythSystemLegacy
Definition: mythsystemlegacy.h:68
MetadataLookup::GetTitle
QString GetTitle() const
Definition: metadatacommon.h:298
doc
QDomDocument doc("MYTHARCHIVEITEM")
MetaGrabberScript::Test
bool Test(void)
Definition: metadatagrabber.cpp:364
MetaGrabberScript::SearchSubtitle
MetadataLookupList SearchSubtitle(const QString &title, const QString &subtitle, MetadataLookup *lookup, bool passseas=true)
Definition: metadatagrabber.cpp:461
kMetadataVideo
@ kMetadataVideo
Definition: metadatacommon.h:42
RemoteFile::Exists
static bool Exists(const QString &url, struct stat *fileinfo)
Definition: remotefile.cpp:461
title
QString title
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:636
MetadataLookup::GetSubtype
LookupType GetSubtype() const
Definition: metadatacommon.h:286
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:50
arg
arg(title).arg(filename).arg(doDelete))
RemoteFile
Definition: remotefile.h:18
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:198
MythSystemLegacy::ReadAll
QByteArray & ReadAll()
Definition: mythsystemlegacy.cpp:397
MetadataDownload::GetTelevisionGrabber
static QString GetTelevisionGrabber()
Definition: metadatadownload.cpp:423
MythSystemLegacy::Run
void Run(time_t timeout=0)
Runs a command inside the /bin/sh shell. Returns immediately.
Definition: mythsystemlegacy.cpp:212
mythdirs.h
MetadataDownload::~MetadataDownload
~MetadataDownload() override
Definition: metadatadownload.cpp:28
MetadataLookup::SetCollectionref
void SetCollectionref(const QString &collectionref)
Definition: metadatacommon.h:269
kLookupSearch
@ kLookupSearch
Definition: metadatacommon.h:27
tmp
static guint32 * tmp
Definition: goom_core.cpp:31
MetadataLookup::GetStep
LookupStep GetStep() const
Definition: metadatacommon.h:288
kGrabberMovie
@ kGrabberMovie
Definition: metadatagrabber.h:22
nearestName
QString nearestName(const QString &actual, const QStringList &candidates)
Definition: metadatacommon.cpp:1378
mythsystemlegacy.h
MetadataDownload::handleMovie
static MetadataLookupList handleMovie(MetadataLookup *lookup)
handleMovie: attempt to find movie data via the following (in order) 1- Local MXML: already done befo...
Definition: metadatadownload.cpp:607
MetadataLookup
Definition: metadatacommon.h:87
MetadataLookupFailure::kEventType
static Type kEventType
Definition: metadatadownload.h:32
MetadataDownload::getNFOPath
static QString getNFOPath(const QString &filename)
Definition: metadatadownload.cpp:832
MetadataLookup::SetEpisode
void SetEpisode(uint episode)
Definition: metadatacommon.h:267
MetaGrabberScript::Search
MetadataLookupList Search(const QString &title, MetadataLookup *lookup, bool passseas=true)
Definition: metadatagrabber.cpp:449
mythlogging.h
MetadataLookup::GetEpisode
uint GetEpisode() const
Definition: metadatacommon.h:314
MetadataLookupFailure
Definition: metadatadownload.h:24
remotefile.h
metadatadownload.h
RefCountedList< MetadataLookup >
MetadataDownload::m_parent
QObject * m_parent
Definition: metadatadownload.h:86
kLookupData
@ kLookupData
Definition: metadatacommon.h:28
getNameWithExtension
static QString getNameWithExtension(const QString &filename, const QString &type)
Definition: metadatadownload.cpp:804
MetadataLookup::GetType
MetadataType GetType() const
Definition: metadatacommon.h:285
kArtworkFanart
@ kArtworkFanart
Definition: metadataimagehelper.h:12
MetadataLookup::GetSubtitle
QString GetSubtitle() const
Definition: metadatacommon.h:309
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:637
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:211
MetadataDownload::readNFO
static MetadataLookupList readNFO(const QString &NFOpath, MetadataLookup *lookup)
Definition: metadatadownload.cpp:510
storagegroup.h
kLookupCollection
@ kLookupCollection
Definition: metadatacommon.h:29
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:758
MetadataLookup::GetCollectionref
QString GetCollectionref() const
Definition: metadatacommon.h:356
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:266
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:647
MetaGrabberScript::GetGrabber
static MetaGrabberScript GetGrabber(GrabberType defaultType, const MetadataLookup *lookup=nullptr)
Definition: metadatagrabber.cpp:127
MetadataLookup::GetAllowGeneric
bool GetAllowGeneric() const
Definition: metadatacommon.h:294
MetadataLookup::GetSeason
uint GetSeason() const
Definition: metadatacommon.h:313
MetadataLookup::GetFilename
QString GetFilename() const
Definition: metadatacommon.h:297
kUnknownVideo
@ kUnknownVideo
Definition: metadatacommon.h:53
MetadataLookup::GetBaseTitle
QString GetBaseTitle() const
Definition: metadatacommon.h:299
mythuihelper.h
MetadataDownload::handleGame
static MetadataLookupList handleGame(MetadataLookup *lookup)
Definition: metadatadownload.cpp:565
MetadataDownload::getMXMLPath
static QString getMXMLPath(const QString &filename)
Definition: metadatadownload.cpp:827
MetadataLookupEvent::kEventType
static Type kEventType
Definition: metadatadownload.h:20
mythmiscutil.h
MetadataDownload::MovieGrabberWorks
static bool MovieGrabberWorks()
Definition: metadatadownload.cpp:438
mythcorecontext.h
MetadataLookup::SetAutomatic
void SetAutomatic(bool autom)
Definition: metadatacommon.h:245
kGrabberGame
@ kGrabberGame
Definition: metadatagrabber.h:25
MetadataLookup::GetInetref
QString GetInetref() const
Definition: metadatacommon.h:355
MetadataLookup::SetInetref
void SetInetref(const QString &inetref)
Definition: metadatacommon.h:268
MetaGrabberScript::LookupData
MetadataLookupList LookupData(const QString &inetref, MetadataLookup *lookup, bool passseas=true)
Definition: metadatagrabber.cpp:490
MetadataDownload::handleVideoUndetermined
static MetadataLookupList handleVideoUndetermined(MetadataLookup *lookup)
Definition: metadatadownload.cpp:735
kMetadataGame
@ kMetadataGame
Definition: metadatacommon.h:45
LookupType
LookupType
Definition: metadatacommon.h:49
MetaGrabberScript::GetType
GrabberType GetType(void) const
Definition: metadatagrabber.h:64
metadatafactory.h
MThread::isRunning
bool isRunning(void) const
Definition: mthread.cpp:268
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:889
MThread::wait
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:305
MetadataLookup::GetAutomatic
bool GetAutomatic() const
Definition: metadatacommon.h:289
MetadataDownload::GetGameGrabber
static QString GetGameGrabber()
Definition: metadatadownload.cpp:428
ParseMetadataMovieNFO
MetadataLookup * ParseMetadataMovieNFO(const QDomElement &item, MetadataLookup *lookup)
Definition: metadatacommon.cpp:1150
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:101
kProbableMovie
@ kProbableMovie
Definition: metadatacommon.h:52
MetadataLookupEvent
Definition: metadatadownload.h:12
kMSStdOut
@ kMSStdOut
allow access to stdout
Definition: mythsystem.h:39
kArtworkCoverart
@ kArtworkCoverart
Definition: metadataimagehelper.h:11
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:243
MetadataLookupList
RefCountedList< MetadataLookup > MetadataLookupList
Definition: metadatacommon.h:461
MythSystemLegacy::Wait
uint Wait(time_t timeout=0)
Definition: mythsystemlegacy.cpp:242
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