MythTV  master
metadatafactory.cpp
Go to the documentation of this file.
1 
2 #include "metadatafactory.h"
3 
4 // C++
5 #include <algorithm>
6 #include <unistd.h> // for sleep()
7 using std::max;
8 
9 // QT
10 #include <QApplication>
11 #include <QList>
12 #include <QUrl>
13 
14 // libmythbase
15 #include "mythlogging.h"
16 #include "compat.h"
17 
18 // libmyth
19 #include "mythcontext.h"
20 #include "remoteutil.h"
21 
22 // libmythmetadata
23 #include "videoutils.h"
24 
25 // Needed to perform a lookup
26 #include "metadatadownload.h"
27 #include "metadataimagedownload.h"
28 
29 // Needed for video scanning
31 #include "globals.h"
32 
33 // Input for a lookup
34 #include "videometadata.h"
35 #include "programinfo.h"
36 #include "recordingrule.h"
37 
38 
40  (QEvent::Type) QEvent::registerEventType();
41 
43  (QEvent::Type) QEvent::registerEventType();
44 
46  (QEvent::Type) QEvent::registerEventType();
47 
49  (QEvent::Type) QEvent::registerEventType();
50 
52  QObject(parent)
53 {
54  m_lookupthread = new MetadataDownload(this);
57 
59 }
60 
62 {
63  if (m_lookupthread)
64  {
66  delete m_lookupthread;
67  m_lookupthread = nullptr;
68  }
69 
70  if (m_imagedownload)
71  {
73  delete m_imagedownload;
74  m_imagedownload = nullptr;
75  }
76 
78  delete m_videoscanner;
79 
80  delete m_mlm;
81  m_mlm = nullptr;
82 }
83 
84 void MetadataFactory::Lookup(RecordingRule *recrule, bool automatic,
85  bool getimages, bool allowgeneric)
86 {
87  if (!recrule)
88  return;
89 
90  auto *lookup = new MetadataLookup();
91 
92  lookup->SetStep(kLookupSearch);
93  lookup->SetType(kMetadataRecording);
94  lookup->SetSubtype(GuessLookupType(recrule));
95  lookup->SetData(qVariantFromValue(recrule));
96  lookup->SetAutomatic(automatic);
97  lookup->SetHandleImages(getimages);
98  lookup->SetAllowGeneric(allowgeneric);
99  lookup->SetHost(gCoreContext->GetMasterHostName());
100  lookup->SetTitle(recrule->m_title);
101  lookup->SetSubtitle(recrule->m_subtitle);
102  lookup->SetInetref(recrule->m_inetref);
103  lookup->SetSeason(recrule->m_season);
104  lookup->SetEpisode(recrule->m_episode);
105 
106  if (m_lookupthread->isRunning())
107  m_lookupthread->prependLookup(lookup);
108  else
109  m_lookupthread->addLookup(lookup);
110 }
111 
112 void MetadataFactory::Lookup(ProgramInfo *pginfo, bool automatic,
113  bool getimages, bool allowgeneric)
114 {
115  if (!pginfo)
116  return;
117 
118  auto *lookup = new MetadataLookup();
119 
120  lookup->SetStep(kLookupSearch);
121  lookup->SetType(kMetadataRecording);
122  lookup->SetSubtype(GuessLookupType(pginfo));
123  lookup->SetData(qVariantFromValue(pginfo));
124  lookup->SetAutomatic(automatic);
125  lookup->SetHandleImages(getimages);
126  lookup->SetAllowGeneric(allowgeneric);
127  lookup->SetHost(gCoreContext->GetMasterHostName());
128  lookup->SetTitle(pginfo->GetTitle());
129  lookup->SetSubtitle(pginfo->GetSubtitle());
130  lookup->SetSeason(pginfo->GetSeason());
131  lookup->SetEpisode(pginfo->GetEpisode());
132  lookup->SetInetref(pginfo->GetInetRef());
133 
134  if (m_lookupthread->isRunning())
135  m_lookupthread->prependLookup(lookup);
136  else
137  m_lookupthread->addLookup(lookup);
138 }
139 
140 void MetadataFactory::Lookup(VideoMetadata *metadata, bool automatic,
141  bool getimages, bool allowgeneric)
142 {
143  if (!metadata)
144  return;
145 
146  auto *lookup = new MetadataLookup();
147 
148  lookup->SetStep(kLookupSearch);
149  lookup->SetType(kMetadataVideo);
150  lookup->SetSubtype(GuessLookupType(metadata));
151  lookup->SetData(qVariantFromValue(metadata));
152  lookup->SetAutomatic(automatic);
153  lookup->SetHandleImages(getimages);
154  lookup->SetAllowGeneric(allowgeneric);
155  lookup->SetHost(metadata->GetHost());
156  lookup->SetTitle(metadata->GetTitle());
157  lookup->SetSubtitle(metadata->GetSubtitle());
158  lookup->SetSeason(metadata->GetSeason());
159  lookup->SetEpisode(metadata->GetEpisode());
160  lookup->SetInetref(metadata->GetInetRef());
161  lookup->SetFilename(generate_file_url("Videos", metadata->GetHost(),
162  metadata->GetFilename()));
163 
164  if (m_lookupthread->isRunning())
165  m_lookupthread->prependLookup(lookup);
166  else
167  m_lookupthread->addLookup(lookup);
168 }
169 
171 {
172  if (!lookup)
173  return;
174 
175  if (m_lookupthread->isRunning())
176  m_lookupthread->prependLookup(lookup);
177  else
178  m_lookupthread->addLookup(lookup);
179 }
180 
182  const QString& subtitle,
183  const QString& inetref,
184  int season,
185  int episode,
186  const QString& grabber,
187  bool allowgeneric)
188 {
189  auto *lookup = new MetadataLookup();
190 
191  lookup->SetStep(kLookupSearch);
192  lookup->SetType(kMetadataRecording);
193  lookup->SetAutomatic(false);
194  lookup->SetHandleImages(false);
195  lookup->SetAllowGeneric(allowgeneric);
196  lookup->SetTitle(title);
197  lookup->SetSubtitle(subtitle);
198  lookup->SetSeason(season);
199  lookup->SetEpisode(episode);
200  lookup->SetInetref(inetref);
201  if (grabber.toLower() == "movie")
202  lookup->SetSubtype(kProbableMovie);
203  else if (grabber.toLower() == "tv" ||
204  grabber.toLower() == "television")
205  lookup->SetSubtype(kProbableTelevision);
206  else
207  lookup->SetSubtype(GuessLookupType(lookup));
208 
209  return SynchronousLookup(lookup);
210 }
211 
213 {
214  if (!lookup)
215  return MetadataLookupList();
216 
217  m_sync = true;
218 
219  if (m_lookupthread->isRunning())
220  m_lookupthread->prependLookup(lookup);
221  else
222  m_lookupthread->addLookup(lookup);
223 
224  while (m_returnList.isEmpty() && m_sync)
225  {
226  sleep(1);
227  qApp->processEvents();
228  }
229 
230  m_sync = false;
231 
232  return m_returnList;
233 }
234 
236 {
239 }
240 
242 {
243  if (IsRunning())
244  return;
245 
246  QStringList hosts;
247  if (!RemoteGetActiveBackends(&hosts))
248  {
249  LOG(VB_GENERAL, LOG_WARNING, "Could not retrieve list of "
250  "available backends.");
251  return;
252  }
253 
254  VideoScan(hosts);
255 }
256 
257 void MetadataFactory::VideoScan(const QStringList& hosts)
258 {
259  if (IsRunning())
260  return;
261 
262  m_scanning = true;
263 
264  m_videoscanner->SetHosts(hosts);
267 }
268 
270 {
271  if (list.isEmpty())
272  return;
273 
274  if (parent())
275  QCoreApplication::postEvent(parent(),
276  new MetadataFactoryMultiResult(list));
277 }
278 
280 {
281  if (!lookup)
282  return;
283 
284  if (lookup->GetHandleImages())
285  {
286  DownloadMap map;
287 
288  ArtworkList coverartlist = lookup->GetArtwork(kArtworkCoverart);
289  if (!coverartlist.empty())
290  {
291  ArtworkInfo info;
292  info.url = coverartlist.takeFirst().url;
293  map.insert(kArtworkCoverart, info);
294  }
295 
296  ArtworkList fanartlist = lookup->GetArtwork(kArtworkFanart);
297  if (!fanartlist.empty())
298  {
299  ArtworkInfo info;
300  int index = 0;
301  int season = lookup->GetIsCollection() ? 0 : (int)lookup->GetSeason();
302  if (season > 0 && season <= fanartlist.count())
303  index = season - 1;
304  info.url = fanartlist.takeAt(index).url;
305  map.insert(kArtworkFanart, info);
306  }
307 
308  ArtworkList bannerlist = lookup->GetArtwork(kArtworkBanner);
309  if (!bannerlist.empty())
310  {
311  ArtworkInfo info;
312  info.url = bannerlist.takeFirst().url;
313  map.insert(kArtworkBanner, info);
314  }
315 
316  if (lookup->GetType() != kMetadataRecording)
317  {
318  ArtworkList screenshotlist = lookup->GetArtwork(kArtworkScreenshot);
319  if (!screenshotlist.empty())
320  {
321  ArtworkInfo info;
322  info.url = screenshotlist.takeFirst().url;
323  map.insert(kArtworkScreenshot, info);
324  }
325  }
326  lookup->SetDownloads(map);
327  lookup->IncrRef();
328  m_imagedownload->addDownloads(lookup);
329  }
330  else
331  {
332  if (m_scanning)
333  OnVideoResult(lookup);
334  else if (parent())
335  QCoreApplication::postEvent(parent(),
336  new MetadataFactorySingleResult(lookup));
337  }
338 }
339 
341 {
342  if (!lookup)
343  return;
344 
345  if (parent())
346  QCoreApplication::postEvent(parent(),
347  new MetadataFactoryNoResult(lookup));
348 }
349 
351 {
352  if (!lookup)
353  return;
354 
355  if (parent())
356  QCoreApplication::postEvent(parent(),
357  new MetadataFactorySingleResult(lookup));
358 }
359 
361 {
362  if (!lookup)
363  return;
364 
365  auto *metadata = lookup->GetData().value<VideoMetadata *>();
366 
367  if (!metadata)
368  return;
369 
370  metadata->SetTitle(lookup->GetTitle());
371  metadata->SetSubtitle(lookup->GetSubtitle());
372 
373  if (metadata->GetTagline().isEmpty())
374  metadata->SetTagline(lookup->GetTagline());
375  if (metadata->GetYear() == VIDEO_YEAR_DEFAULT || metadata->GetYear() == 0)
376  metadata->SetYear(lookup->GetYear());
377  if (metadata->GetReleaseDate() == QDate())
378  metadata->SetReleaseDate(lookup->GetReleaseDate());
379  if (metadata->GetDirector() == VIDEO_DIRECTOR_UNKNOWN ||
380  metadata->GetDirector().isEmpty())
381  {
382  QList<PersonInfo> director = lookup->GetPeople(kPersonDirector);
383  if (director.count() > 0)
384  metadata->SetDirector(director.takeFirst().name);
385  }
386  if (metadata->GetStudio().isEmpty())
387  {
388  QStringList studios = lookup->GetStudios();
389  if (studios.count() > 0)
390  metadata->SetStudio(studios.takeFirst());
391  }
392  if (metadata->GetPlot() == VIDEO_PLOT_DEFAULT ||
393  metadata->GetPlot().isEmpty())
394  metadata->SetPlot(lookup->GetDescription());
395  if (metadata->GetUserRating() == 0)
396  metadata->SetUserRating(lookup->GetUserRating());
397  if (metadata->GetRating() == VIDEO_RATING_DEFAULT)
398  metadata->SetRating(lookup->GetCertification());
399  if (metadata->GetLength() == 0)
400  metadata->SetLength(lookup->GetRuntime());
401  if (metadata->GetSeason() == 0)
402  metadata->SetSeason(lookup->GetSeason());
403  if (metadata->GetEpisode() == 0)
404  metadata->SetEpisode(lookup->GetEpisode());
405  if (metadata->GetHomepage().isEmpty())
406  metadata->SetHomepage(lookup->GetHomepage());
407 
408  metadata->SetInetRef(lookup->GetInetref());
409 
410 // m_d->AutomaticParentalAdjustment(metadata);
411 
412  // Cast
413  QList<PersonInfo> actors = lookup->GetPeople(kPersonActor);
414  QList<PersonInfo> gueststars = lookup->GetPeople(kPersonGuestStar);
415 
416  for (QList<PersonInfo>::const_iterator p = gueststars.begin();
417  p != gueststars.end(); ++p)
418  {
419  actors.append(*p);
420  }
421 
423  QStringList cl;
424 
425  for (QList<PersonInfo>::const_iterator p = actors.begin();
426  p != actors.end(); ++p)
427  {
428  cl.append((*p).name);
429  }
430 
431  for (QStringList::const_iterator p = cl.begin();
432  p != cl.end(); ++p)
433  {
434  QString cn = (*p).trimmed();
435  if (cn.length())
436  {
437  cast.push_back(VideoMetadata::cast_list::
438  value_type(-1, cn));
439  }
440  }
441 
442  metadata->SetCast(cast);
443 
444  // Genres
445  VideoMetadata::genre_list video_genres;
446  QStringList genres = lookup->GetCategories();
447 
448  for (QStringList::const_iterator p = genres.begin();
449  p != genres.end(); ++p)
450  {
451  QString genre_name = (*p).trimmed();
452  if (genre_name.length())
453  {
454  video_genres.push_back(
455  VideoMetadata::genre_list::value_type(-1, genre_name));
456  }
457  }
458 
459  metadata->SetGenres(video_genres);
460 
461  // Countries
462  VideoMetadata::country_list video_countries;
463  QStringList countries = lookup->GetCountries();
464 
465  for (QStringList::const_iterator p = countries.begin();
466  p != countries.end(); ++p)
467  {
468  QString country_name = (*p).trimmed();
469  if (country_name.length())
470  {
471  video_countries.push_back(
472  VideoMetadata::country_list::value_type(-1,
473  country_name));
474  }
475  }
476 
477  metadata->SetCountries(video_countries);
478 
479  ArtworkMap map = lookup->GetDownloads();
480 
481  QUrl coverurl(map.value(kArtworkCoverart).url);
482  if (!coverurl.path().isEmpty())
483  metadata->SetCoverFile(coverurl.path().remove(0,1));
484 
485  QUrl fanarturl(map.value(kArtworkFanart).url);
486  if (!fanarturl.path().isEmpty())
487  metadata->SetFanart(fanarturl.path().remove(0,1));
488 
489  QUrl bannerurl(map.value(kArtworkBanner).url);
490  if (!bannerurl.path().isEmpty())
491  metadata->SetBanner(bannerurl.path().remove(0,1));
492 
493  QUrl sshoturl(map.value(kArtworkScreenshot).url);
494  if (!sshoturl.path().isEmpty())
495  metadata->SetScreenshot(sshoturl.path().remove(0,1));
496 
497  metadata->SetProcessed(true);
498  metadata->UpdateDatabase();
499 
500  if (gCoreContext->HasGUI() && parent())
501  {
502  QCoreApplication::postEvent(parent(),
503  new MetadataFactorySingleResult(lookup));
504  }
505 }
506 
507 void MetadataFactory::customEvent(QEvent *levent)
508 {
509  if (levent->type() == MetadataLookupEvent::kEventType)
510  {
511  auto lue = dynamic_cast<MetadataLookupEvent *>(levent);
512  if (lue == nullptr)
513  return;
514 
515  MetadataLookupList lul = lue->m_lookupList;
516  if (lul.isEmpty())
517  return;
518 
519  if (m_sync)
520  {
521  m_returnList = lul;
522  }
523  else if (lul.count() == 1)
524  {
525  OnSingleResult(lul[0]);
526  }
527  else
528  {
529  OnMultiResult(lul);
530  }
531  }
532  else if (levent->type() == MetadataLookupFailure::kEventType)
533  {
534  auto luf = dynamic_cast<MetadataLookupFailure *>(levent);
535  if (luf == nullptr)
536  return;
537 
538  MetadataLookupList lul = luf->m_lookupList;
539  if (lul.isEmpty())
540  return;
541 
542  if (m_sync)
543  {
545  m_sync = false;
546  }
547  if (!lul.empty())
548  {
549  OnNoResult(lul[0]);
550  }
551  }
552  else if (levent->type() == ImageDLEvent::kEventType)
553  {
554  auto *ide = dynamic_cast<ImageDLEvent *>(levent);
555  if (ide == nullptr)
556  return;
557 
558  MetadataLookup *lookup = ide->m_item;
559  if (!lookup)
560  return;
561 
562  if (m_scanning)
563  OnVideoResult(lookup);
564  else
565  OnImageResult(lookup);
566  }
567  else if (levent->type() == ImageDLFailureEvent::kEventType)
568  {
569  auto *ide = dynamic_cast<ImageDLFailureEvent *>(levent);
570  if (ide == nullptr)
571  return;
572 
573  MetadataLookup *lookup = ide->m_item;
574  if (!lookup)
575  return;
576 
577  // propagate event on image download failure
578  if (parent())
579  QCoreApplication::postEvent(parent(),
580  new ImageDLFailureEvent(lookup));
581  }
582  else if (levent->type() == VideoScanChanges::kEventType)
583  {
584  auto *vsc = dynamic_cast<VideoScanChanges *>(levent);
585  if (!vsc)
586  return;
587 
588  QList<int> additions = vsc->m_additions;
589  QList<int> moves = vsc->m_moved;
590  QList<int> deletions = vsc->m_deleted;
591 
592  if (!m_scanning)
593  {
594  LOG(VB_GENERAL, LOG_INFO,
595  QString("Video Scan Complete: a(%1) m(%2) d(%3)")
596  .arg(additions.count()).arg(moves.count())
597  .arg(deletions.count()));
598 
599  if (parent())
600  QCoreApplication::postEvent(parent(),
601  new MetadataFactoryVideoChanges(additions, moves,
602  deletions));
603  }
604  else
605  {
606  LOG(VB_GENERAL, LOG_INFO,
607  QString("Video Scan Complete: a(%1) m(%2) d(%3)")
608  .arg(additions.count()).arg(moves.count())
609  .arg(deletions.count()));
610 
613  m_mlm->setList(ml);
614 
615  for (QList<int>::const_iterator it = additions.begin();
616  it != additions.end(); ++it)
617  {
618  VideoMetadata *metadata = m_mlm->byID(*it).get();
619 
620  if (metadata)
621  Lookup(metadata, true, true);
622  }
623  }
625  }
626 }
627 
628 // These functions exist to determine if we have enough
629 // information to conclusively call something a Show vs. Movie
630 
632 {
633  LookupType ret = GuessLookupType(pginfo->GetInetRef());
634 
635  if (ret != kUnknownVideo)
636  return ret;
637 
638  ProgramInfo::CategoryType catType = pginfo->GetCategoryType();
639  if (catType == ProgramInfo::kCategoryNone)
640  catType = pginfo->QueryCategoryType();
641 
642  if ((!pginfo->GetSubtitle().isEmpty() || pginfo->GetEpisode() > 0) &&
643  (catType == ProgramInfo::kCategorySeries ||
644  catType == ProgramInfo::kCategoryTVShow))
645  ret = kProbableTelevision; // NOLINT(bugprone-branch-clone)
646  else if (catType == ProgramInfo::kCategoryMovie)
647  ret = kProbableMovie;
648  else if (pginfo->GetSeason() > 0 || pginfo->GetEpisode() > 0 ||
649  !pginfo->GetSubtitle().isEmpty())
650  ret = kProbableTelevision;
651  else
652  {
653  // Before committing to something being a movie, we
654  // want to check its rule. If the rule has a season
655  // or episode number, but the recording doesn't,
656  // and the rec doesn't have a subtitle, this is a
657  // generic recording. If neither the rule nor the
658  // recording have an inetref, season, episode, or
659  // subtitle, it's *probably* a movie. If it's some
660  // weird combination of both, we've got to try everything.
661  auto *rule = new RecordingRule();
662  rule->m_recordID = pginfo->GetRecordingRuleID();
663  rule->Load();
664  int ruleepisode = rule->m_episode;
665  delete rule;
666 
667  if (ruleepisode == 0 && pginfo->GetEpisode() == 0 &&
668  pginfo->GetSubtitle().isEmpty())
669  ret = kProbableMovie;
670  else if (ruleepisode > 0 && pginfo->GetSubtitle().isEmpty())
672  else
673  ret = kUnknownVideo;
674  }
675 
676  return ret;
677 }
678 
680 {
681  LookupType ret = GuessLookupType(lookup->GetInetref());
682 
683  if (ret != kUnknownVideo)
684  return ret;
685 
686  if (lookup->GetSeason() > 0 || lookup->GetEpisode() > 0 ||
687  !lookup->GetSubtitle().isEmpty())
688  ret = kProbableTelevision;
689  else
690  ret = kProbableMovie;
691 
692  return ret;
693 }
694 
696 {
697  LookupType ret = GuessLookupType(metadata->GetInetRef());
698 
699  if (ret != kUnknownVideo)
700  return ret;
701 
702  if (metadata->GetSeason() > 0 || metadata->GetEpisode() > 0 ||
703  !metadata->GetSubtitle().isEmpty())
704  ret = kProbableTelevision;
705  else
706  ret = kProbableMovie;
707 
708  return ret;
709 }
710 
712 {
713  LookupType ret = GuessLookupType(recrule->m_inetref);
714 
715  if (ret != kUnknownVideo)
716  return ret;
717 
718  if (recrule->m_season > 0 || recrule->m_episode > 0 ||
719  !recrule->m_subtitle.isEmpty())
720  ret = kProbableTelevision;
721  else
722  ret = kProbableMovie;
723 
724  return ret;
725 }
726 
727 LookupType GuessLookupType(const QString &inetref)
728 {
729  if (inetref.isEmpty() || inetref == "00000000" ||
730  inetref == MetaGrabberScript::CleanedInetref(inetref))
731  {
732  // can't determine subtype from inetref
733  return kUnknownVideo;
734  }
735 
736  // inetref is defined, see if we have a pre-defined grabber
737  MetaGrabberScript grabber =
739 
740  if (!grabber.IsValid())
741  {
742  return kUnknownVideo;
743  }
744 
745  switch (grabber.GetType())
746  {
747  case kGrabberMovie:
748  return kProbableMovie;
749  case kGrabberTelevision:
750  return kProbableTelevision;
751  default:
752  return kUnknownVideo;
753  }
754 }
QString m_subtitle
Definition: recordingrule.h:81
RefCountedList< MetadataLookup > MetadataLookupList
QStringList GetCategories() const
void start(QThread::Priority=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:294
ArtworkList GetArtwork(VideoArtworkType type) const
QStringList GetVideoDirs()
Definition: videoutils.cpp:122
static bool MovieGrabberWorks()
MetadataLookupList SynchronousLookup(const QString &title, const QString &subtitle, const QString &inetref, int season, int episode, const QString &grabber, bool allowgeneric=false)
int GetSeason() const
static void loadAllFromDatabase(metadata_list &items, const QString &sql="")
Load videometadata database into memory.
static QString CleanedInetref(const QString &inetref)
uint GetYear() const
bool HasGUI(void) const
std::vector< country_entry > country_list
Definition: videometadata.h:33
bool GetIsCollection() const
QString GetDescription() const
LookupType GuessLookupType(ProgramInfo *pginfo)
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:311
MetadataFactory(QObject *parent)
void SetHosts(const QStringList &hosts)
Definition: videoscan.cpp:101
QString GetTitle(void) const
Definition: programinfo.h:353
void OnSingleResult(MetadataLookup *lookup)
VideoMetadataListManager * m_mlm
std::vector< cast_entry > cast_list
Definition: videometadata.h:34
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void OnNoResult(MetadataLookup *lookup)
QList< PersonInfo > GetPeople(PeopleType type) const
CategoryType QueryCategoryType(void) const
Queries recordedprogram to get the category_type of the recording.
static MetaGrabberScript GetType(const QString &type)
void prependLookup(MetadataLookup *lookup)
prependLookup: Add lookup to top of the queue MetadataDownload::m_lookupList takes ownership of the g...
static bool VideoGrabbersFunctional()
QList< ArtworkInfo > ArtworkList
unsigned sleep(unsigned int x)
Definition: compat.h:159
QString GetInetRef(void) const
Definition: programinfo.h:429
QString GetSubtitle() const
void SetDirs(QStringList dirs)
Definition: videoscan.cpp:109
QStringList GetStudios() const
MetadataType GetType() const
float GetUserRating() const
uint GetSeason() const
QString GetTitle() const
uint GetEpisode() const
bool IsValid(void) const
Holds information on recordings and videos.
Definition: programinfo.h:66
bool RemoteGetActiveBackends(QStringList *list)
return list of backends currently connected to the master
Definition: remoteutil.cpp:578
QString GetTagline() const
void setList(metadata_list &list)
virtual int IncrRef(void)
Increments reference count.
const QString VIDEO_PLOT_DEFAULT
Definition: globals.cpp:32
#define META_PUBLIC
Definition: mythmetaexp.h:9
int GetEpisode() const
MetadataDownload * m_lookupthread
QStringList GetCountries() const
void addDownloads(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_downloadList takes ownership of the ...
void ResetCounts()
Definition: videoscan.h:72
bool isRunning(void) const
Definition: mthread.cpp:274
QString GetSubtitle(void) const
Definition: programinfo.h:355
void OnImageResult(MetadataLookup *lookup)
QString GetMasterHostName(void)
uint GetSeason(void) const
Definition: programinfo.h:358
std::vector< genre_entry > genre_list
Definition: videometadata.h:32
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:32
void SetDownloads(ArtworkMap map)
QString GetInetref() const
void OnVideoResult(MetadataLookup *lookup)
const QString & GetHost() const
QVariant GetData() const
void customEvent(QEvent *levent) override
QString m_inetref
Definition: recordingrule.h:96
void SetTitle(const QString &title, const QString &sortTitle="")
QDate GetReleaseDate() const
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
QMap< VideoArtworkType, ArtworkInfo > DownloadMap
const QString & GetFilename() const
MetadataLookupList m_returnList
const QString VIDEO_DIRECTOR_UNKNOWN
Definition: globals.cpp:9
static Type kEventType
QString m_title
Definition: recordingrule.h:79
void Lookup(ProgramInfo *pginfo, bool automatic=true, bool getimages=true, bool allowgeneric=false)
QString GetHomepage() const
uint GetRecordingRuleID(void) const
Definition: programinfo.h:441
VideoMetadataPtr byID(unsigned int db_id) const
bool GetHandleImages() const
uint GetRuntime() const
QString generate_file_url(const QString &storage_group, const QString &host, const QString &path)
Definition: videoutils.h:65
T * get() const
Definition: quicksp.h:65
const QString VIDEO_RATING_DEFAULT
Definition: globals.cpp:30
DownloadMap GetDownloads() const
const QString & GetSubtitle() const
void OnMultiResult(const MetadataLookupList &list)
MetadataImageDownload * m_imagedownload
QMultiMap< VideoArtworkType, ArtworkInfo > ArtworkMap
static Type kEventType
Definition: videoscan.h:54
const QString & GetInetRef() const
const QString & GetTitle() const
void addLookup(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_lookupList takes ownership of the gi...
static bool TelevisionGrabberWorks()
LookupType
static MetaGrabberScript FromInetref(const QString &inetref, bool absolute=false)
CategoryType GetCategoryType(void) const
Definition: programinfo.h:430
VideoScannerThread * m_videoscanner
QString GetCertification() const
uint GetEpisode(void) const
Definition: programinfo.h:359
std::list< VideoMetadataPtr > metadata_list