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
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 sleep(1);
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 for (const auto& actor : std::as_const(gueststars))
443 actors.append(actor);
444
446 QStringList cl;
447
448 for (const auto& actor : std::as_const(actors))
449 cl.append(actor.name);
450
451 for (const auto& name : std::as_const(cl))
452 {
453 QString cn = name.trimmed();
454 if (!cn.isEmpty())
455 {
456 cast.emplace_back(-1, cn);
457 }
458 }
459
460 metadata->SetCast(cast);
461
462 // Genres
463 VideoMetadata::genre_list video_genres;
464 QStringList genres = lookup->GetCategories();
465
466 for (const auto& str : std::as_const(genres))
467 {
468 QString genre_name = str.trimmed();
469 if (!genre_name.isEmpty())
470 {
471 video_genres.emplace_back(-1, genre_name);
472 }
473 }
474
475 metadata->SetGenres(video_genres);
476
477 // Countries
478 VideoMetadata::country_list video_countries;
479 QStringList countries = lookup->GetCountries();
480
481 for (const auto& str : std::as_const(countries))
482 {
483 QString country_name = str.trimmed();
484 if (!country_name.isEmpty())
485 {
486 video_countries.emplace_back(-1, country_name);
487 }
488 }
489
490 metadata->SetCountries(video_countries);
491
492 DownloadMap map = lookup->GetDownloads();
493
494 QUrl coverurl(map.value(kArtworkCoverart).url);
495 if (!coverurl.path().isEmpty())
496 metadata->SetCoverFile(coverurl.path().remove(0,1));
497
498 QUrl fanarturl(map.value(kArtworkFanart).url);
499 if (!fanarturl.path().isEmpty())
500 metadata->SetFanart(fanarturl.path().remove(0,1));
501
502 QUrl bannerurl(map.value(kArtworkBanner).url);
503 if (!bannerurl.path().isEmpty())
504 metadata->SetBanner(bannerurl.path().remove(0,1));
505
506 QUrl sshoturl(map.value(kArtworkScreenshot).url);
507 if (!sshoturl.path().isEmpty())
508 metadata->SetScreenshot(sshoturl.path().remove(0,1));
509
510 metadata->SetProcessed(true);
511 metadata->UpdateDatabase();
512
513 if (gCoreContext->HasGUI() && parent())
514 {
515 QCoreApplication::postEvent(parent(),
516 new MetadataFactorySingleResult(lookup));
517 }
518}
519
521{
522 if (levent->type() == MetadataLookupEvent::kEventType)
523 {
524 auto *lue = dynamic_cast<MetadataLookupEvent *>(levent);
525 if (lue == nullptr)
526 return;
527
528 MetadataLookupList lul = lue->m_lookupList;
529 if (lul.isEmpty())
530 return;
531
532 if (m_sync)
533 {
534 m_returnList = lul;
535 }
536 else if (lul.count() == 1)
537 {
538 OnSingleResult(lul[0]);
539 }
540 else
541 {
542 OnMultiResult(lul);
543 }
544 }
545 else if (levent->type() == MetadataLookupFailure::kEventType)
546 {
547 auto *luf = dynamic_cast<MetadataLookupFailure *>(levent);
548 if (luf == nullptr)
549 return;
550
551 MetadataLookupList lul = luf->m_lookupList;
552 if (lul.isEmpty())
553 return;
554
555 if (m_sync)
556 {
558 m_sync = false;
559 }
560 if (!lul.empty())
561 {
562 OnNoResult(lul[0]);
563 }
564 }
565 else if (levent->type() == ImageDLEvent::kEventType)
566 {
567 auto *ide = dynamic_cast<ImageDLEvent *>(levent);
568 if (ide == nullptr)
569 return;
570
571 MetadataLookup *lookup = ide->m_item;
572 if (!lookup)
573 return;
574
575 if (m_scanning)
576 OnVideoResult(lookup);
577 else
578 OnImageResult(lookup);
579 }
580 else if (levent->type() == ImageDLFailureEvent::kEventType)
581 {
582 auto *ide = dynamic_cast<ImageDLFailureEvent *>(levent);
583 if (ide == nullptr)
584 return;
585
586 MetadataLookup *lookup = ide->m_item;
587 if (!lookup)
588 return;
589
590 // propagate event on image download failure
591 if (parent())
592 QCoreApplication::postEvent(parent(),
593 new ImageDLFailureEvent(lookup));
594 }
595 else if (levent->type() == VideoScanChanges::kEventType)
596 {
597 auto *vsc = dynamic_cast<VideoScanChanges *>(levent);
598 if (!vsc)
599 return;
600
601 QList<int> additions = vsc->m_additions;
602 QList<int> moves = vsc->m_moved;
603 QList<int> deletions = vsc->m_deleted;
604
605 if (!m_scanning)
606 {
607 LOG(VB_GENERAL, LOG_INFO,
608 QString("Video Scan Complete: a(%1) m(%2) d(%3)")
609 .arg(additions.count()).arg(moves.count())
610 .arg(deletions.count()));
611
612 if (parent())
613 {
614 QCoreApplication::postEvent(parent(),
615 new MetadataFactoryVideoChanges(additions, moves,
616 deletions));
617 }
618 }
619 else
620 {
621 LOG(VB_GENERAL, LOG_INFO,
622 QString("Video Scan Complete: a(%1) m(%2) d(%3)")
623 .arg(additions.count()).arg(moves.count())
624 .arg(deletions.count()));
625
628 m_mlm->setList(ml);
629
630 for (int id : std::as_const(additions))
631 {
632 VideoMetadata *metadata = m_mlm->byID(id).get();
633
634 if (metadata)
635 Lookup(metadata, true, true);
636 }
637 }
639 }
640}
641
642// These functions exist to determine if we have enough
643// information to conclusively call something a Show vs. Movie
644
646{
647 LookupType ret = GuessLookupType(pginfo->GetInetRef());
648
649 if (ret != kUnknownVideo)
650 return ret;
651
652 ProgramInfo::CategoryType catType = pginfo->GetCategoryType();
653 if (catType == ProgramInfo::kCategoryNone)
654 catType = pginfo->QueryCategoryType();
655
656 if ((!pginfo->GetSubtitle().isEmpty() || pginfo->GetEpisode() > 0) &&
657 (catType == ProgramInfo::kCategorySeries ||
659 ret = kProbableTelevision; // NOLINT(bugprone-branch-clone)
660 else if (catType == ProgramInfo::kCategoryMovie)
661 ret = kProbableMovie;
662 else if (pginfo->GetSeason() > 0 || pginfo->GetEpisode() > 0 ||
663 !pginfo->GetSubtitle().isEmpty())
665 else
666 {
667 // Before committing to something being a movie, we
668 // want to check its rule. If the rule has a season
669 // or episode number, but the recording doesn't,
670 // and the rec doesn't have a subtitle, this is a
671 // generic recording. If neither the rule nor the
672 // recording have an inetref, season, episode, or
673 // subtitle, it's *probably* a movie. If it's some
674 // weird combination of both, we've got to try everything.
675 auto *rule = new RecordingRule();
676 rule->m_recordID = pginfo->GetRecordingRuleID();
677 // Load rule information from the database
678 rule->Load();
679 int ruleepisode = rule->m_episode;
680 RecordingType rulerectype = rule->m_type;
681 delete rule;
682
683 // If recording rule is periodic, it's probably a TV show.
684 if ((rulerectype == kDailyRecord) ||
685 (rulerectype == kWeeklyRecord))
686 {
688 }
689 else if (ruleepisode == 0 && pginfo->GetEpisode() == 0 &&
690 pginfo->GetSubtitle().isEmpty())
691 {
692 ret = kProbableMovie;
693 }
694 else if (ruleepisode > 0 && pginfo->GetSubtitle().isEmpty())
695 {
697 }
698 else
699 {
700 ret = kUnknownVideo;
701 }
702 }
703
704 return ret;
705}
706
708{
709 LookupType ret = GuessLookupType(lookup->GetInetref());
710
711 if (ret != kUnknownVideo)
712 return ret;
713
714 if (lookup->GetSeason() > 0 || lookup->GetEpisode() > 0 ||
715 !lookup->GetSubtitle().isEmpty())
717 else
718 ret = kProbableMovie;
719
720 return ret;
721}
722
724{
725 LookupType ret = GuessLookupType(metadata->GetInetRef());
726
727 if (ret != kUnknownVideo)
728 return ret;
729
730 if (metadata->GetSeason() > 0 || metadata->GetEpisode() > 0 ||
731 !metadata->GetSubtitle().isEmpty())
733 else
734 ret = kProbableMovie;
735
736 return ret;
737}
738
740{
741 LookupType ret = GuessLookupType(recrule->m_inetref);
742
743 if (ret != kUnknownVideo)
744 return ret;
745
746 if (recrule->m_season > 0 || recrule->m_episode > 0 ||
747 (recrule->m_type == kDailyRecord) ||
748 (recrule->m_type == kWeeklyRecord) ||
749 !recrule->m_subtitle.isEmpty())
751 else
752 ret = kProbableMovie;
753
754 return ret;
755}
756
757LookupType GuessLookupType(const QString &inetref)
758{
759 if (inetref.isEmpty() || inetref == "00000000" ||
760 inetref == MetaGrabberScript::CleanedInetref(inetref))
761 {
762 // can't determine subtype from inetref
763 return kUnknownVideo;
764 }
765
766 // inetref is defined, see if we have a pre-defined grabber
767 MetaGrabberScript grabber =
769
770 if (!grabber.IsValid())
771 {
772 return kUnknownVideo;
773 }
774
775 switch (grabber.GetType())
776 {
777 case kGrabberMovie:
778 return kProbableMovie;
780 return kProbableTelevision;
781 default:
782 return kUnknownVideo;
783 }
784}
static const Type kEventType
static const Type kEventType
bool isRunning(void) const
Definition: mthread.cpp:263
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
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:70
uint GetRecordingRuleID(void) const
Definition: programinfo.h:455
uint GetEpisode(void) const
Definition: programinfo.h:370
QString GetInetRef(void) const
Definition: programinfo.h:443
CategoryType QueryCategoryType(void) const
Queries recordedprogram to get the category_type of the recording.
QString GetTitle(void) const
Definition: programinfo.h:364
CategoryType GetCategoryType(void) const
Definition: programinfo.h:444
QString GetSubtitle(void) const
Definition: programinfo.h:366
uint GetSeason(void) const
Definition: programinfo.h:369
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:30
RecordingType m_type
QString m_inetref
Definition: recordingrule.h:88
QString m_title
Definition: recordingrule.h:78
QString m_subtitle
Definition: recordingrule.h:80
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:75
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:487
QStringList GetVideoDirs()
Definition: videoutils.cpp:116