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