MythTV master
videometadata.cpp
Go to the documentation of this file.
1#include <algorithm>
2#include <cmath> // for isnan()
3
4#include <QDir>
5#include <QFile>
6#include <QFileInfo>
7#include <QRegularExpression>
8
11#include "libmythbase/mythdb.h"
13#include "libmythbase/mythmiscutil.h"// for FileHash
18
19#include "dbaccess.h"
20#include "globals.h"
22#include "videoutils.h"
23
25{
26 public:
30
31 public:
32 VideoMetadataImp(QString filename, QString sortFilename,
33 QString hash, QString trailer,
34 QString coverfile, QString screenshot, QString banner,
35 QString fanart, const QString &title, QString sortTitle,
36 const QString &subtitle, QString sortSubtitle,
37 QString tagline, int year, const QDate releasedate,
38 QString inetref, int collectionref, QString homepage,
39 QString director, QString studio,
40 QString plot, float userrating,
41 QString rating, int length, int playcount,
42 int season, int episode, const QDate insertdate,
43 int id, ParentalLevel::Level showlevel, int categoryID,
44 int childID, bool browse, bool watched,
45 QString playcommand, QString category,
46 genre_list genres,
47 country_list countries,
48 cast_list cast,
49 QString host = "",
50 bool processed = false,
51 VideoContentType contenttype = kContentUnknown) :
52 m_title(title), m_sortTitle(std::move(sortTitle)), m_subtitle(subtitle),
53 m_sortSubtitle(std::move(sortSubtitle)), m_tagline(std::move(tagline)),
54 m_inetref(std::move(inetref)), m_collectionref(collectionref),
55 m_homepage(std::move(homepage)), m_director(std::move(director)),
56 m_studio(std::move(studio)), m_plot(std::move(plot)),
57 m_rating(std::move(rating)), m_playcommand(std::move(playcommand)),
58 m_category(std::move(category)), m_genres(std::move(genres)),
59 m_countries(std::move(countries)), m_cast(std::move(cast)),
60 m_filename(std::move(filename)), m_sortFilename(std::move(sortFilename)),
61 m_hash(std::move(hash)), m_trailer(std::move(trailer)),
62 m_coverfile(std::move(coverfile)), m_screenshot(std::move(screenshot)),
63 m_banner(std::move(banner)), m_fanart(std::move(fanart)),
64 m_host(std::move(host)), m_categoryID(categoryID), m_childID(childID),
65 m_year(year), m_releasedate(releasedate), m_length(length), m_playcount(playcount),
66 m_season(season), m_episode(episode), m_insertdate(insertdate), m_showlevel(showlevel),
67 m_browse(browse), m_watched(watched), m_id(id),
68 m_userrating(userrating), m_processed(processed),
69 m_contenttype(contenttype)
70 {
71 // Try to glean data if none provided.
72 if (title.isEmpty() and subtitle.isEmpty()
73 and season == 0 and episode == 0)
74 {
79 }
80
82
84 }
85
86 explicit VideoMetadataImp(MSqlQuery &query)
87 {
88 fromDBRow(query);
90 }
91
93 {
94 *this = other;
95 }
96
98 {
99 if (this != &rhs)
100 {
101 m_title = rhs.m_title;
105 m_tagline = rhs.m_tagline;
106 m_inetref = rhs.m_inetref;
110 m_studio = rhs.m_studio;
111 m_plot = rhs.m_plot;
112 m_rating = rhs.m_rating;
115 m_genres = rhs.m_genres;
117 m_cast = rhs.m_cast;
120 m_hash = rhs.m_hash;
121 m_trailer = rhs.m_trailer;
124 m_banner = rhs.m_banner;
125 m_fanart = rhs.m_fanart;
126
128 m_childID = rhs.m_childID;
129 m_year = rhs.m_year;
131 m_length = rhs.m_length;
133 m_season = rhs.m_season;
134 m_episode = rhs.m_episode;
137 m_browse = rhs.m_browse;
138 m_watched = rhs.m_watched;
139 m_id = rhs.m_id;
141 m_host = rhs.m_host;
144
145 // No DB vars
146 m_prefix = rhs.m_prefix;
147
149 }
150
151 return *this;
152 }
153
155 {
156 std::shared_ptr<MythSortHelper>sh = getMythSortHelper();
157 if (m_sortTitle.isEmpty() and not m_title.isEmpty())
158 m_sortTitle = sh->doTitle(m_title);
159 if (m_sortSubtitle.isEmpty() and not m_subtitle.isEmpty())
160 m_sortSubtitle = sh->doTitle(m_subtitle);
161 if (m_sortFilename.isEmpty() and not m_filename.isEmpty())
162 m_sortFilename = sh->doPathname(m_filename);
163 }
164
165 public:
166 const QString &GetPrefix() const { return m_prefix; }
167 void SetPrefix(const QString &prefix) { m_prefix = prefix; }
168
169 const QString &getTitle() const { return m_title; }
170 const QString &getSortTitle() const { return m_sortTitle; }
171 void SetTitle(const QString& title, const QString& sortTitle = "")
172 {
173 m_title = title;
174 m_sortTitle = sortTitle;
176 }
177
178 const QString &getSubtitle() const { return m_subtitle; }
179 const QString &getSortSubtitle() const { return m_sortSubtitle; }
180 void SetSubtitle(const QString &subtitle, const QString &sortSubtitle = "") {
181 m_subtitle = subtitle;
182 m_sortSubtitle = sortSubtitle;
184 }
185
186 const QString &GetTagline() const { return m_tagline; }
187 void SetTagline(const QString &tagline) { m_tagline = tagline; }
188
189 const QString &GetInetRef() const { return m_inetref; }
190 void SetInetRef(const QString &inetRef) { m_inetref = inetRef; }
191
192 int GetCollectionRef() const { return m_collectionref; }
193 void SetCollectionRef(int collectionref) { m_collectionref = collectionref; }
194
195 const QString &GetHomepage() const { return m_homepage; }
196 void SetHomepage(const QString &homepage) { m_homepage = homepage; }
197
198 const QString &getDirector() const { return m_director; }
199 void SetDirector(const QString &director) { m_director = director; }
200
201 const QString &getStudio() const { return m_studio; }
202 void SetStudio(const QString &studio) { m_studio = studio; }
203
204 const QString &getPlot() const { return m_plot; }
205 void SetPlot(const QString &plot) { m_plot = plot; }
206
207 const QString &GetRating() const { return m_rating; }
208 void SetRating(const QString &rating) { m_rating = rating; }
209
210 const QString &getPlayCommand() const { return m_playcommand; }
211 void SetPlayCommand(const QString &playCommand)
212 {
213 m_playcommand = playCommand;
214 }
215
216 const QString &GetCategory() const { return m_category; }
217// void SetCategory(const QString &category) { m_category = category; }
218
219 const genre_list &getGenres() const { return m_genres; }
220 void SetGenres(const genre_list &genres) { m_genres = genres; }
221
222 const country_list &GetCountries() const { return m_countries; }
223 void SetCountries(const country_list &countries)
224 {
225 m_countries = countries;
226 }
227
228 const cast_list &GetCast() const { return m_cast; }
229 void SetCast(const cast_list &cast) { m_cast = cast; }
230
231 const QString &GetHost() const { return m_host; }
232 void SetHost(const QString &host) { m_host = host; }
233
234 const QString &getFilename() const { return m_filename; }
235 const QString &getSortFilename() const { return m_sortFilename; }
236 void SetFilename(const QString &filename, const QString &sortFilename = "")
237 {
239 m_sortFilename = sortFilename;
241 }
242
243 bool sortBefore(const VideoMetadataImp *rhs) const;
244
245 const QString &GetHash() const { return m_hash; }
246 void SetHash(const QString &hash) { m_hash = hash; }
247
248 const QString &GetTrailer() const { return m_trailer; }
249 void SetTrailer(const QString &trailer) { m_trailer = trailer; }
250
251 const QString &GetCoverFile() const { return m_coverfile; }
252 void SetCoverFile(const QString &coverFile) { m_coverfile = coverFile; }
253
254 const QString &GetScreenshot() const { return m_screenshot; }
255 void SetScreenshot(const QString &screenshot) { m_screenshot = screenshot; }
256
257 const QString &GetBanner() const { return m_banner; }
258 void SetBanner(const QString &banner) { m_banner = banner; }
259
260 const QString &GetFanart() const { return m_fanart; }
261 void SetFanart(const QString &fanart) { m_fanart = fanart; }
262
263 int GetCategoryID() const
264 {
265 return m_categoryID;
266 }
267 void SetCategoryID(int id);
268
269 int GetChildID() const { return m_childID; }
270 void SetChildID(int childID) { m_childID = childID; }
271
272 int getYear() const { return m_year; }
273 void SetYear(int year) { m_year = year; }
274
275 QDate getReleaseDate() const { return m_releasedate; }
276 void SetReleaseDate(QDate releasedate) { m_releasedate = releasedate; }
277
278 std::chrono::minutes GetLength() const { return m_length; }
279 void SetLength(std::chrono::minutes length) { m_length = length; }
280
281 unsigned int GetPlayCount() const { return m_playcount; }
282 void SetPlayCount(int playcount) { m_playcount = playcount; }
283
284 int GetSeason() const { return m_season; }
285 void SetSeason(int season) { m_season = season; }
286
287 int GetEpisode() const { return m_episode; }
288 void SetEpisode(int episode) { m_episode = episode; }
289
290 QDate GetInsertdate() const { return m_insertdate;}
291 void SetInsertdate(QDate date) { m_insertdate = date;}
292
295 {
296 m_showlevel = ParentalLevel(showLevel).GetLevel();
297 }
298
299 bool GetBrowse() const { return m_browse; }
300 void SetBrowse(bool browse) { m_browse = browse; }
301
302 bool GetWatched() const { return m_watched; }
303 void SetWatched(bool watched) { m_watched = watched; }
304
305 unsigned int GetID() const { return m_id; }
306 void SetID(int id) { m_id = id; }
307
308 float GetUserRating() const { return m_userrating; }
309 void SetUserRating(float userRating) { m_userrating = userRating; }
310
311 bool GetProcessed() const { return m_processed; }
312 void SetProcessed(bool processed) { m_processed = processed; }
313
315 void SetContentType(VideoContentType contenttype) { m_contenttype = contenttype; }
316
318
319 void SaveToDatabase();
320 void UpdateDatabase();
321 bool DeleteFromDatabase();
322
323 bool DeleteFile();
324
325 void Reset();
326
327 bool IsHostSet() const;
328
329 void GetImageMap(InfoMap &imageMap) const;
330 QString GetImage(const QString &name) const;
331
332 private:
333 void fillCountries();
334 void updateCountries();
335 void fillGenres();
336 void fillCast();
337 void updateGenres();
338 void updateCast();
339 bool removeDir(const QString &dirName);
340 void fromDBRow(MSqlQuery &query);
341 void saveToDatabase();
342
343 private:
344 QString m_title;
345 QString m_sortTitle;
346 QString m_subtitle;
348 QString m_tagline;
349 QString m_inetref;
351 QString m_homepage;
352 QString m_director;
353 QString m_studio;
354 QString m_plot;
355 QString m_rating;
357 QString m_category;
361 QString m_filename;
363 QString m_hash;
364 QString m_trailer;
365 QString m_coverfile;
367 QString m_banner;
368 QString m_fanart;
369 QString m_host;
370
372 int m_childID {-1};
375 std::chrono::minutes m_length {0min};
376 int m_playcount {0};
377 int m_season {0};
378 int m_episode {0};
381 bool m_browse {true};
382 bool m_watched {false};
383 unsigned int m_id {0}; // videometadata.intid
384 float m_userrating {0.0};
385 bool m_processed {false};
387
388 // not in DB
389 QString m_prefix;
390};
391
395
396// For the spaceship operator, the c++ standard library explicitly
397// requires '0' and not nullptr. NOLINTBEGIN(modernize-use-nullptr)
398
403{
405 if (cmp == 0)
407 if (cmp == 0)
408 cmp = m_id <=> rhs->m_id;
409 return cmp < 0;
410}
411// NOLINTEND(modernize-use-nullptr)
412
413bool VideoMetadataImp::removeDir(const QString &dirName)
414{
415 QDir d(dirName);
416
417 d.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
418 QFileInfoList contents = d.entryInfoList();
419 if (contents.empty())
420 {
421 return d.rmdir(dirName);
422 }
423
424 for (const auto& entry : std::as_const(contents))
425 {
426 if (entry.isDir())
427 {
428 QString fileName = entry.fileName();
429 if (!removeDir(fileName))
430 return false;
431 }
432 else
433 {
434 if (!QFile(entry.fileName()).remove())
435 return false;
436 }
437 }
438 return d.rmdir(dirName);
439}
440
443{
444 bool isremoved = false;
445
446 if (!m_host.isEmpty())
447 {
448 QString url = StorageGroup::generate_file_url("Videos", m_host, m_filename);
449 isremoved = RemoteFile::DeleteFile(url);
450 }
451 else
452 {
453 QFileInfo fi(m_filename);
454 if (fi.isDir())
455 {
456 isremoved = removeDir(m_filename);
457 }
458 else
459 {
460 isremoved = QFile::remove(m_filename);
461 }
462 }
463
464 if (!isremoved)
465 {
466 LOG(VB_GENERAL, LOG_DEBUG, QString("Could not delete file: %1")
467 .arg(m_filename));
468 }
469
470 return isremoved;
471}
472
474{
475 VideoMetadataImp tmp(m_filename, QString(),
478 VIDEO_FANART_DEFAULT, QString(), QString(), QString(), QString(),
479 QString(), VIDEO_YEAR_DEFAULT,
480 QDate(), VIDEO_INETREF_DEFAULT, -1, QString(), VIDEO_DIRECTOR_DEFAULT,
481 QString(), VIDEO_PLOT_DEFAULT, 0.0,
483 0, 0, QDate(), m_id,
484 ParentalLevel::plLowest, 0, -1, true, false, "", "",
487 tmp.m_prefix = m_prefix;
488
489 *this = tmp;
490}
491
493{
494 return !m_host.isEmpty();
495}
496
498{
499 m_genres.clear();
502 if (vgm.get(m_id, genres))
503 {
505 for (long value : genres.values)
506 {
507 // Just add empty string for no-name genres
508 QString name;
509 vg.get(value, name);
510 m_genres.emplace_back(value, name);
511 }
512 }
513}
514
516{
517 m_countries.clear();
519 VideoCountryMap::entry countries;
520 if (vcm.get(m_id, countries))
521 {
523 for (long value : countries.values)
524 {
525 // Just add empty string for no-name countries
526 QString name;
527 vc.get(value, name);
528 m_countries.emplace_back(value, name);
529 }
530 }
531}
532
534{
535 m_cast.clear();
538 if (vcm.get(m_id, cast))
539 {
541 for (long value : cast.values)
542 {
543 // Just add empty string for no-name cast
544 QString name;
545 vc.get(value, name);
546 m_cast.emplace_back(value, name);
547 }
548 }
549}
550
556{
557 m_title = query.value(0).toString();
558 m_director = query.value(1).toString();
559 m_studio = query.value(2).toString();
560 m_plot = query.value(3).toString();
561 m_rating = query.value(4).toString();
562 m_year = query.value(5).toInt();
563 m_releasedate = query.value(6).toDate();
564 m_userrating = (float)query.value(7).toDouble();
565 if (std::isnan(m_userrating) || m_userrating < 0)
566 m_userrating = 0.0;
567 m_userrating = std::min(m_userrating, 10.0F);
568 m_length = std::chrono::minutes(query.value(8).toInt());
569 m_playcount = query.value(9).toInt();
570 m_filename = query.value(10).toString();
571 m_hash = query.value(11).toString();
572 m_showlevel = ParentalLevel(query.value(12).toInt()).GetLevel();
573 m_coverfile = query.value(13).toString();
574 m_inetref = query.value(14).toString();
575 m_collectionref = query.value(15).toUInt();
576 m_homepage = query.value(16).toString();
577 m_childID = query.value(17).toUInt();
578 m_browse = query.value(18).toBool();
579 m_watched = query.value(19).toBool();
580 m_playcommand = query.value(20).toString();
581 m_categoryID = query.value(21).toInt();
582 m_id = query.value(22).toInt();
583 m_trailer = query.value(23).toString();
584 m_screenshot = query.value(24).toString();
585 m_banner = query.value(25).toString();
586 m_fanart = query.value(26).toString();
587 m_subtitle = query.value(27).toString();
588 m_tagline = query.value(28).toString();
589 m_season = query.value(29).toInt();
590 m_episode = query.value(30).toInt();
591 m_host = query.value(31).toString();
592 m_insertdate = query.value(32).toDate();
593 m_processed = query.value(33).toBool();
594
595 m_contenttype = ContentTypeFromString(query.value(34).toString());
596
598
600
601 // Genres
602 fillGenres();
603
604 //Countries
606
607 // Cast
608 fillCast();
609}
610
612{
613 if (m_title.isEmpty())
615 if (m_hash.isEmpty())
617 if (m_subtitle.isEmpty())
619 if (m_director.isEmpty())
621 if (m_plot.isEmpty())
623 if (m_rating.isEmpty())
626
627 InfoMap metadataMap;
628 GetImageMap(metadataMap);
629 QString coverfile = metadataMap["coverfile"];
630 QString screenshot = metadataMap["screenshotfile"];
631 QString bannerfile = metadataMap["bannerfile"];
632 QString fanartfile = metadataMap["fanartfile"];
633
634 if (coverfile.isEmpty() || !RemoteFile::Exists(coverfile))
636 if (screenshot.isEmpty() || !RemoteFile::Exists(screenshot))
638 if (bannerfile.isEmpty() || !RemoteFile::Exists(bannerfile))
640 if (fanartfile.isEmpty() || !RemoteFile::Exists(fanartfile))
642 if (m_trailer.isEmpty())
644 if (m_inetref.isEmpty())
646 if (std::isnan(m_userrating))
647 m_userrating = 0.0;
648 if (m_userrating < -10.0F || m_userrating > 10.0F)
649 m_userrating = 0.0;
650 if (m_releasedate.toString().isEmpty())
651 m_releasedate = QDate::fromString("0000-00-00", "YYYY-MM-DD");
653 {
654 if (m_season > 0 || m_episode > 0)
656 else
658 }
659
660 bool inserting = m_id == 0;
661
663
664 if (inserting)
665 {
666 m_browse = true;
667
668 m_watched = false;
669
670 query.prepare("INSERT INTO videometadata (title,subtitle,tagline,director,studio,plot,"
671 "rating,year,userrating,length,season,episode,filename,hash,"
672 "showlevel,coverfile,inetref,homepage,browse,watched,trailer,"
673 "screenshot,banner,fanart,host,processed,contenttype) VALUES (:TITLE, :SUBTITLE, "
674 ":TAGLINE, :DIRECTOR, :STUDIO, :PLOT, :RATING, :YEAR, :USERRATING, "
675 ":LENGTH, :SEASON, :EPISODE, :FILENAME, :HASH, :SHOWLEVEL, "
676 ":COVERFILE, :INETREF, :HOMEPAGE, :BROWSE, :WATCHED, "
677 ":TRAILER, :SCREENSHOT, :BANNER, :FANART, :HOST, :PROCESSED, :CONTENTTYPE)");
678 }
679 else
680 {
681 query.prepare("UPDATE videometadata SET title = :TITLE, subtitle = :SUBTITLE, "
682 "tagline = :TAGLINE, director = :DIRECTOR, studio = :STUDIO, "
683 "plot = :PLOT, rating= :RATING, year = :YEAR, "
684 "releasedate = :RELEASEDATE, userrating = :USERRATING, "
685 "length = :LENGTH, playcount = :PLAYCOUNT, season = :SEASON, "
686 "episode = :EPISODE, filename = :FILENAME, hash = :HASH, trailer = :TRAILER, "
687 "showlevel = :SHOWLEVEL, coverfile = :COVERFILE, "
688 "screenshot = :SCREENSHOT, banner = :BANNER, fanart = :FANART, "
689 "inetref = :INETREF, collectionref = :COLLECTION, homepage = :HOMEPAGE, "
690 "browse = :BROWSE, watched = :WATCHED, host = :HOST, playcommand = :PLAYCOMMAND, "
691 "childid = :CHILDID, category = :CATEGORY, processed = :PROCESSED, "
692 "contenttype = :CONTENTTYPE WHERE intid = :INTID");
693
694 query.bindValue(":PLAYCOMMAND", m_playcommand);
695 query.bindValue(":CHILDID", m_childID);
696 query.bindValue(":CATEGORY", m_categoryID);
697 query.bindValue(":INTID", m_id);
698 }
699
700 query.bindValueNoNull(":TITLE", m_title);
701 query.bindValueNoNull(":SUBTITLE", m_subtitle);
702 query.bindValue(":TAGLINE", m_tagline);
703 query.bindValueNoNull(":DIRECTOR", m_director);
704 query.bindValue(":STUDIO", m_studio);
705 query.bindValue(":PLOT", m_plot);
706 query.bindValueNoNull(":RATING", m_rating);
707 query.bindValue(":YEAR", m_year);
708 query.bindValue(":RELEASEDATE", m_releasedate);
709 query.bindValue(":USERRATING", m_userrating);
710 query.bindValue(":LENGTH", static_cast<qint64>(m_length.count()));
711 query.bindValue(":PLAYCOUNT", m_playcount);
712 query.bindValue(":SEASON", m_season);
713 query.bindValue(":EPISODE", m_episode);
714 query.bindValue(":FILENAME", m_filename);
715 query.bindValue(":HASH", m_hash);
716 query.bindValueNoNull(":TRAILER", m_trailer);
717 query.bindValue(":SHOWLEVEL", m_showlevel);
718 query.bindValueNoNull(":COVERFILE", m_coverfile);
719 query.bindValueNoNull(":SCREENSHOT", m_screenshot);
720 query.bindValueNoNull(":BANNER", m_banner);
721 query.bindValueNoNull(":FANART", m_fanart);
722 query.bindValueNoNull(":INETREF", m_inetref);
723 query.bindValue(":COLLECTION", m_collectionref);
724 query.bindValueNoNull(":HOMEPAGE", m_homepage);
725 query.bindValue(":BROWSE", m_browse);
726 query.bindValue(":WATCHED", m_watched);
727 query.bindValue(":HOST", m_host);
728 query.bindValue(":PROCESSED", m_processed);
729 query.bindValue(":CONTENTTYPE", ContentTypeToString(m_contenttype));
730
731 if (!query.exec() || !query.isActive())
732 {
733 MythDB::DBError("video metadata update", query);
734 return;
735 }
736
737 if (inserting)
738 {
739 // Must make sure we have 'id' filled before we call updateGenres or
740 // updateCountries
741
742 if (!query.exec("SELECT LAST_INSERT_ID()") || !query.next())
743 {
744 MythDB::DBError("metadata id get", query);
745 return;
746 }
747
748 m_id = query.value(0).toUInt();
749
750 if (0 == m_id)
751 {
752 LOG(VB_GENERAL, LOG_ERR,
753 QString("%1: The id of the last inserted row to "
754 "videometadata seems to be 0. This is odd.")
755 .arg(__FILE__));
756 return;
757 }
758 }
759
760 updateGenres();
762 updateCast();
763}
764
766{
768}
769
771{
773}
774
776{
780
782 query.prepare("DELETE FROM videometadata WHERE intid = :ID");
783 query.bindValue(":ID", m_id);
784 if (!query.exec())
785 {
786 MythDB::DBError("delete from videometadata", query);
787 }
788
789 query.prepare("DELETE FROM filemarkup WHERE filename = :FILENAME");
790 query.bindValue(":FILENAME", m_filename);
791 if (!query.exec())
792 {
793 MythDB::DBError("delete from filemarkup", query);
794 }
795
796 return true;
797}
798
800{
801 if (id == 0)
802 {
803 m_category = "";
804 m_categoryID = id;
805 }
806 else
807 {
808 if (m_categoryID != id)
809 {
810 QString cat;
812 {
813 m_category = cat;
814 m_categoryID = id;
815 }
816 else
817 {
818 LOG(VB_GENERAL, LOG_ERR, "Unknown category id");
819 }
820 }
821 }
822}
823
825{
827
828 // ensure that all genres we have are in the DB
829 auto genre = m_genres.begin();
830 while (genre != m_genres.end())
831 {
832 if (!genre->second.trimmed().isEmpty())
833 {
834 genre->first = VideoGenre::getGenre().add(genre->second);
835 VideoGenreMap::getGenreMap().add(m_id, genre->first);
836 ++genre;
837 }
838 else
839 {
840 genre = m_genres.erase(genre);
841 }
842 }
843}
844
846{
847 // remove countries for this video
849
850 auto country = m_countries.begin();
851 while (country != m_countries.end())
852 {
853 if (!country->second.trimmed().isEmpty())
854 {
855 country->first = VideoCountry::getCountry().add(country->second);
856 VideoCountryMap::getCountryMap().add(m_id, country->first);
857 ++country;
858 }
859 else
860 {
861 country = m_countries.erase(country);
862 }
863 }
864}
865
867{
869
870 // ensure that all cast we have are in the DB
871 auto cast = m_cast.begin();
872 while (cast != m_cast.end())
873 {
874 if (!cast->second.trimmed().isEmpty())
875 {
876 cast->first = VideoCast::GetCast().add(cast->second);
877 VideoCastMap::getCastMap().add(m_id, cast->first);
878 ++cast;
879 }
880 else
881 {
882 cast = m_cast.erase(cast);
883 }
884 }
885}
886
888{
889 QString coverfile;
890 if (IsHostSet()
891 && !GetCoverFile().startsWith(u'/')
892 && !GetCoverFile().isEmpty()
894 {
895 coverfile = StorageGroup::generate_file_url(QStringLiteral(u"Coverart"), GetHost(),
896 GetCoverFile());
897 }
898 else
899 {
900 coverfile = GetCoverFile();
901 }
902
903 imageMap[QStringLiteral(u"coverfile")] = coverfile;
904 imageMap[QStringLiteral(u"coverart")] = coverfile;
905
906 QString screenshotfile;
907 if (IsHostSet() && !GetScreenshot().startsWith(u'/')
908 && !GetScreenshot().isEmpty())
909 {
910 screenshotfile = StorageGroup::generate_file_url(QStringLiteral(u"Screenshots"),
912 }
913 else
914 {
915 screenshotfile = GetScreenshot();
916 }
917
918 imageMap[QStringLiteral(u"screenshotfile")] = screenshotfile;
919 imageMap[QStringLiteral(u"screenshot")] = screenshotfile;
920
921 QString bannerfile;
922 if (IsHostSet() && !GetBanner().startsWith(u'/')
923 && !GetBanner().isEmpty())
924 {
925 bannerfile = StorageGroup::generate_file_url(QStringLiteral(u"Banners"), GetHost(),
926 GetBanner());
927 }
928 else
929 {
930 bannerfile = GetBanner();
931 }
932
933 imageMap[QStringLiteral(u"bannerfile")] = bannerfile;
934 imageMap[QStringLiteral(u"banner")] = bannerfile;
935
936 QString fanartfile;
937 if (IsHostSet() && !GetFanart().startsWith('/')
938 && !GetFanart().isEmpty())
939 {
940 fanartfile = StorageGroup::generate_file_url(QStringLiteral(u"Fanart"), GetHost(),
941 GetFanart());
942 }
943 else
944 {
945 fanartfile = GetFanart();
946 }
947
948 imageMap[QStringLiteral(u"fanartfile")] = fanartfile;
949 imageMap[QStringLiteral(u"fanart")] = fanartfile;
950
951 QString smartimage = coverfile;
952 if (!screenshotfile.isEmpty () && (GetSeason() > 0 || GetEpisode() > 0))
953 smartimage = screenshotfile;
954 imageMap[QStringLiteral(u"smartimage")] = smartimage;
955}
956
957// This should be the equivalent of GetImageMap, only the image names
958// are computed one at a time as needed.
959QString VideoMetadataImp::GetImage(const QString& name) const
960{
961 if ((name == QStringLiteral(u"coverfile")) ||
962 (name == QStringLiteral(u"coverart")))
963 {
964 QString coverfile = GetCoverFile();
965 if (IsHostSet()
966 && !coverfile.startsWith(u'/')
967 && !coverfile.isEmpty()
968 && !IsDefaultCoverFile(coverfile))
969 return StorageGroup::generate_file_url(QStringLiteral(u"Coverart"), GetHost(),
970 coverfile);
971 return coverfile;
972 }
973
974 if ((name == QStringLiteral(u"screenshotfile")) ||
975 (name == QStringLiteral(u"screenshot")))
976 {
977 QString screenshot = GetScreenshot();
978 if (IsHostSet() && !screenshot.startsWith(u'/')
979 && !screenshot.isEmpty())
980 return StorageGroup::generate_file_url(QStringLiteral(u"Screenshots"),
981 GetHost(), screenshot);
982 return screenshot;
983 }
984
985 if ((name == QStringLiteral(u"bannerfile")) ||
986 (name == QStringLiteral(u"banner")))
987 {
988 QString bannerfile = GetBanner();
989 if (IsHostSet() && !bannerfile.startsWith(u'/')
990 && !bannerfile.isEmpty())
991 return StorageGroup::generate_file_url(QStringLiteral(u"Banners"), GetHost(),
992 bannerfile);
993 return bannerfile;
994 }
995
996 if ((name == QStringLiteral(u"fanartfile")) ||
997 (name == QStringLiteral(u"fanart")))
998 {
999 QString fanartfile = GetFanart();
1000 if (IsHostSet() && !fanartfile.startsWith('/')
1001 && !fanartfile.isEmpty())
1002 return StorageGroup::generate_file_url(QStringLiteral(u"Fanart"), GetHost(),
1003 fanartfile);
1004 return fanartfile;
1005 }
1006
1007 if ((name == QStringLiteral(u"smartimage")) ||
1008 (name == QStringLiteral(u"buttonimage")))
1009 {
1010 if (GetSeason() > 0 || GetEpisode() > 0)
1011 {
1012 QString screenshotfile = GetImage("screenshot");
1013 if (!screenshotfile.isEmpty())
1014 return screenshotfile;
1015 }
1016 return GetImage("coverart");
1017 }
1018
1019 return {};
1020}
1021
1025namespace
1026{
1027 QString eatBraces(const QString &title, const QString &left_brace,
1028 const QString &right_brace)
1029 {
1030 QString ret(title);
1031 bool keep_checking = true;
1032
1033 while (keep_checking)
1034 {
1035 int left_position = ret.indexOf(left_brace);
1036 int right_position = ret.indexOf(right_brace);
1037 if (left_position == -1 || right_position == -1)
1038 {
1039 //
1040 // No matching sets of these braces left.
1041 //
1042
1043 keep_checking = false;
1044 }
1045 else
1046 {
1047 if (left_position < right_position)
1048 {
1049 //
1050 // We have a matching set like: ( foo )
1051 //
1052
1053 ret = ret.left(left_position) +
1054 ret.right(ret.length() - right_position - 1);
1055 }
1056 else if (left_position > right_position)
1057 {
1058 //
1059 // We have a matching set like: ) foo (
1060 //
1061
1062 ret = ret.left(right_position) +
1063 ret.right(ret.length() - left_position - 1);
1064 }
1065 }
1066 }
1067
1068 return ret;
1069 }
1070}
1071
1073 const QString &file_name,
1074 const QString &host)
1075{
1077
1078 query.prepare("SELECT intid,filename FROM videometadata WHERE "
1079 "hash = :HASH");
1080 query.bindValue(":HASH", hash);
1081
1082 if (!query.exec() || !query.isActive())
1083 {
1084 MythDB::DBError("Video hashed metadata update", query);
1085 return -1;
1086 }
1087
1088 if (!query.next())
1089 return -1;
1090
1091 int intid = query.value(0).toInt();
1092 QString oldfilename = query.value(1).toString();
1093
1094 query.prepare("UPDATE videometadata SET filename = :FILENAME, "
1095 "host = :HOST WHERE intid = :INTID");
1096 query.bindValue(":FILENAME", file_name);
1097 query.bindValue(":HOST", host);
1098 query.bindValue(":INTID", intid);
1099
1100 if (!query.exec() || !query.isActive())
1101 {
1102 MythDB::DBError("Video hashed metadata update (videometadata)", query);
1103 return -1;
1104 }
1105
1106 query.prepare("UPDATE filemarkup SET filename = :FILENAME "
1107 "WHERE filename = :OLDFILENAME");
1108 query.bindValue(":FILENAME", file_name);
1109 query.bindValue(":OLDFILENAME", oldfilename);
1110
1111 if (!query.exec() || !query.isActive())
1112 {
1113 MythDB::DBError("Video hashed metadata update (filemarkup)", query);
1114 return -1;
1115 }
1116
1117 return intid;
1118}
1119
1120QString VideoMetadata::VideoFileHash(const QString &file_name,
1121 const QString &host)
1122{
1123 if (host.isEmpty())
1124 return FileHash(file_name);
1125
1127 {
1128 StorageGroup sgroup("Videos", host);
1129 QString fullname = sgroup.FindFile(file_name);
1130
1131 return FileHash(fullname);
1132 }
1133
1134 QString url = StorageGroup::generate_file_url("Videos", host, file_name);
1135
1136 return RemoteFile::GetFileHash(url);
1137}
1138
1139QString VideoMetadata::FilenameToMeta(const QString &file_name, int position)
1140{
1141 // position 1 returns title, 2 returns season,
1142 // 3 returns episode, 4 returns subtitle
1143
1144 QString cleanFilename = file_name.left(file_name.lastIndexOf('.'));
1145 static const QRegularExpression kSpaceRE { "%20" };
1146 static const QRegularExpression kUnderscoreRE { "_" };
1147 static const QRegularExpression kDotRE { "\\." };
1148 cleanFilename.replace(kSpaceRE, " ");
1149 cleanFilename.replace(kUnderscoreRE, " ");
1150 cleanFilename.replace(kDotRE, " ");
1151
1152 /*: Word(s) which should be recognized as "season" when parsing a video
1153 * file name. To list more than one word, separate them with a '|'.
1154 */
1155 QString season_translation = tr("Season", "Metadata file name parsing");
1156
1157 /*: Word(s) which should be recognized as "episode" when parsing a video
1158 * file name. To list more than one word, separate them with a '|'.
1159 */
1160 QString episode_translation = tr("Episode", "Metadata file name parsing");
1161
1162 // Primary Regexp
1163 QString separator = "(?:\\s?(?:-|/)?\\s?)?";
1164 QString regexp = QString(
1165 "^(.*[^s0-9])" // Title
1166 "%1" // optional separator
1167 "(?:s|(?:Season|%2))?" // season marker
1168 "%1" // optional separator
1169 "(\\d{1,4})" // Season
1170 "%1" // optional separator
1171 "(?:[ex/]|Episode|%3)" // episode marker
1172 "%1" // optional separator
1173 "(\\d{1,3})" // Episode
1174 "%1" // optional separator
1175 "(.*)$" // Subtitle
1176 ).arg(separator, season_translation, episode_translation);
1177 static const QRegularExpression filename_parse { regexp,
1178 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
1179
1180 // Cleanup Regexp
1181 QString regexp2 = QString("(%1(?:(?:Season|%2)%1\\d*%1)*%1)$")
1182 .arg(separator, season_translation);
1183 static const QRegularExpression title_parse {regexp2,
1184 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
1185
1186 auto match = filename_parse.match(cleanFilename);
1187 if (match.hasMatch())
1188 {
1189 // Return requested value
1190 if (position == 1 && !match.capturedView(1).isEmpty())
1191 {
1192 // Clean up the title
1193 QString title = match.captured(1);
1194 match = title_parse.match(title);
1195 if (match.hasMatch())
1196 title = title.left(match.capturedStart());
1197 title = title.right(title.length() - title.lastIndexOf('/') -1);
1198 return title.trimmed();
1199 }
1200 if (position == 2)
1201 return match.captured(2).trimmed();
1202 if (position == 3)
1203 return match.captured(3).trimmed();
1204 if (position == 4)
1205 return match.captured(4).trimmed();
1206 }
1207 else if (position == 1)
1208 {
1209 QString title = cleanFilename;
1210
1211 // Clean up the title
1212 title = title.right(title.length() -
1213 title.lastIndexOf('/') -1);
1214
1215 // Allow parentheses "()", but remove content inside other braces
1216 title = eatBraces(title, "[", "]");
1217 title = eatBraces(title, "{", "}");
1218 return title.trimmed();
1219 }
1220 else if (position == 2 || position == 3)
1221 {
1222 return {"0"};
1223 }
1224
1225 return {};
1226}
1227
1228VideoMetadata::VideoMetadata(const QString &filename, const QString &sortFilename,
1229 const QString &hash, const QString &trailer, const QString &coverfile,
1230 const QString &screenshot, const QString &banner, const QString &fanart,
1231 const QString &title, const QString &sortTitle,
1232 const QString &subtitle, const QString &sortSubtitle, const QString &tagline,
1233 int year, const QDate releasedate, const QString &inetref, int collectionref,
1234 const QString &homepage, const QString &director, const QString &studio,
1235 const QString &plot, float userrating, const QString &rating,
1236 int length, int playcount, int season, int episode, const QDate insertdate,
1237 int id, ParentalLevel::Level showlevel, int categoryID,
1238 int childID, bool browse, bool watched,
1239 const QString &playcommand, const QString &category,
1240 const genre_list &genres,
1241 const country_list &countries,
1242 const cast_list &cast,
1243 const QString &host, bool processed,
1244 VideoContentType contenttype)
1245{
1246 m_imp = new VideoMetadataImp(filename, sortFilename, hash, trailer, coverfile,
1247 screenshot, banner, fanart, title, sortTitle, subtitle,
1248 sortSubtitle, tagline, year, releasedate, inetref,
1249 collectionref, homepage, director, studio, plot, userrating, rating,
1250 length, playcount, season, episode, insertdate, id, showlevel, categoryID,
1251 childID, browse, watched, playcommand, category, genres, countries,
1252 cast, host, processed, contenttype);
1253}
1254
1256{
1257 delete m_imp;
1258}
1259
1261 : m_imp(new VideoMetadataImp(query))
1262{
1263}
1264
1266{
1267 *this = rhs;
1268}
1269
1271{
1272 if (this != &rhs)
1273 {
1274 m_imp = new VideoMetadataImp(*(rhs.m_imp));
1275 }
1276
1277 return *this;
1278}
1279
1281{
1282 GetImageMap(metadataMap);
1283
1284 metadataMap[QStringLiteral(u"filename")] = GetFilename();
1285 metadataMap[QStringLiteral(u"sortfilename")] = GetSortFilename();
1286 metadataMap[QStringLiteral(u"title")] = GetTitle();
1287 metadataMap[QStringLiteral(u"sorttitle")] = GetSortTitle();
1288 metadataMap[QStringLiteral(u"subtitle")] = GetSubtitle();
1289 metadataMap[QStringLiteral(u"sortsubtitle")] = GetSortSubtitle();
1290 metadataMap[QStringLiteral(u"tagline")] = GetTagline();
1291 metadataMap[QStringLiteral(u"director")] = GetDirector();
1292 metadataMap[QStringLiteral(u"studio")] = GetStudio();
1293 metadataMap[QStringLiteral(u"description0")] = metadataMap[QStringLiteral(u"description")] = GetPlot();
1294 metadataMap[QStringLiteral(u"genres")] = GetDisplayGenres(*this);
1295 metadataMap[QStringLiteral(u"countries")] = GetDisplayCountries(*this);
1296 metadataMap[QStringLiteral(u"cast")] = GetDisplayCast(*this).join(", ");
1297 metadataMap[QStringLiteral(u"rating")] = GetDisplayRating(GetRating());
1298 metadataMap[QStringLiteral(u"length")] = GetDisplayLength(GetLength());
1299 metadataMap[QStringLiteral(u"playcount")] = QString::number(GetPlayCount());
1300 metadataMap[QStringLiteral(u"year")] = GetDisplayYear(GetYear());
1301
1302 metadataMap[QStringLiteral(u"releasedate")] = MythDate::toString(
1304
1305 metadataMap[QStringLiteral(u"userrating")] = GetDisplayUserRating(GetUserRating());
1306
1307 if (GetSeason() > 0 || GetEpisode() > 0)
1308 {
1309 metadataMap[QStringLiteral(u"season")] = StringUtil::intToPaddedString(GetSeason(), 1);
1310 metadataMap[QStringLiteral(u"episode")] = StringUtil::intToPaddedString(GetEpisode(), 1);
1311 QString usingSE = QStringLiteral(u"s%1e%2")
1314 metadataMap[QStringLiteral(u"s##e##")] = metadataMap[QStringLiteral(u"s00e00")] = usingSE;
1315 QString usingX = QStringLiteral(u"%1x%2")
1318 metadataMap[QStringLiteral(u"##x##")] = metadataMap[QStringLiteral(u"00x00")] = usingX;
1319 }
1320 else
1321 {
1322 metadataMap[QStringLiteral(u"s##e##")] = metadataMap[QStringLiteral(u"##x##")] = QString();
1323 metadataMap[QStringLiteral(u"s00e00")] = metadataMap[QStringLiteral(u"00x00")] = QString();
1324 metadataMap[QStringLiteral(u"season")] = metadataMap[QStringLiteral(u"episode")] = QString();
1325 }
1326
1327 GetStateMap(metadataMap);
1328
1329 metadataMap[QStringLiteral(u"insertdate")] = MythDate::toString(
1331 metadataMap[QStringLiteral(u"inetref")] = GetInetRef();
1332 metadataMap[QStringLiteral(u"homepage")] = GetHomepage();
1333 metadataMap[QStringLiteral(u"child_id")] = QString::number(GetChildID());
1334 metadataMap[QStringLiteral(u"browseable")] = GetDisplayBrowse(GetBrowse());
1335 metadataMap[QStringLiteral(u"watched")] = GetDisplayWatched(GetWatched());
1336 metadataMap[QStringLiteral(u"processed")] = GetDisplayProcessed(GetProcessed());
1337 metadataMap[QStringLiteral(u"category")] = GetCategory();
1338}
1339
1340// This should be the equivalent of toMap, only the text strings
1341// are computed one at a time as needed.
1342QString VideoMetadata::GetText(const QString& name) const
1343{
1344 if (name == QStringLiteral(u"filename"))
1345 return GetFilename();
1346 if (name == QStringLiteral(u"sortfilename"))
1347 return GetSortFilename();
1348 if (name == QStringLiteral(u"title"))
1349 return GetTitle();
1350 if (name == QStringLiteral(u"sorttitle"))
1351 return GetSortTitle();
1352 if (name == QStringLiteral(u"subtitle"))
1353 return GetSubtitle();
1354 if (name == QStringLiteral(u"sortsubtitle"))
1355 return GetSortSubtitle();
1356 if (name == QStringLiteral(u"tagline"))
1357 return GetTagline();
1358 if (name == QStringLiteral(u"director"))
1359 return GetDirector();
1360 if (name == QStringLiteral(u"studio"))
1361 return GetStudio();
1362 if ((name == QStringLiteral(u"description")) ||
1363 (name == QStringLiteral(u"description0")))
1364 return GetPlot();
1365 if (name == QStringLiteral(u"genres"))
1366 return GetDisplayGenres(*this);
1367 if (name == QStringLiteral(u"countries"))
1368 return GetDisplayCountries(*this);
1369 if (name == QStringLiteral(u"cast"))
1370 return GetDisplayCast(*this).join(", ");
1371 if (name == QStringLiteral(u"rating"))
1372 return GetDisplayRating(GetRating());
1373 if (name == QStringLiteral(u"length"))
1374 return GetDisplayLength(GetLength());
1375 if (name == QStringLiteral(u"playcount"))
1376 return QString::number(GetPlayCount());
1377 if (name == QStringLiteral(u"year"))
1378 return GetDisplayYear(GetYear());
1379
1380 if (name == QStringLiteral(u"releasedate"))
1382
1383 if (name == QStringLiteral(u"userrating"))
1385
1386 if (GetSeason() > 0 || GetEpisode() > 0)
1387 {
1388 if (name == QStringLiteral(u"season"))
1390 if (name == QStringLiteral(u"episode"))
1392 if ((name == QStringLiteral(u"s##e##")) ||
1393 (name == QStringLiteral(u"s00e00")))
1394 {
1395 return QStringLiteral(u"s%1e%2")
1398 }
1399 if ((name == QStringLiteral(u"##x##")) ||
1400 (name == QStringLiteral(u"00x00")))
1401 {
1402 return QStringLiteral(u"%1x%2")
1405 }
1406 }
1407
1408 if (name == QStringLiteral(u"insertdate"))
1409 return MythDate::toString(
1411 if (name == QStringLiteral(u"inetref"))
1412 return GetInetRef();
1413 if (name == QStringLiteral(u"homepage"))
1414 return GetHomepage();
1415 if (name == QStringLiteral(u"child_id"))
1416 return QString::number(GetChildID());
1417 if (name == QStringLiteral(u"browseable"))
1418 return GetDisplayBrowse(GetBrowse());
1419 if (name == QStringLiteral(u"watched"))
1420 return GetDisplayWatched(GetWatched());
1421 if (name == QStringLiteral(u"processed"))
1423 if (name == QStringLiteral(u"category"))
1424 return GetCategory();
1425 return {};
1426}
1427
1429{
1430 stateMap[QStringLiteral(u"trailerstate")] = TrailerToState(GetTrailer());
1431 stateMap[QStringLiteral(u"userratingstate")] =
1432 QString::number((int)(GetUserRating()));
1433 stateMap[QStringLiteral(u"watchedstate")] = WatchedToState(GetWatched());
1434 stateMap[QStringLiteral(u"videolevel")] = ParentalLevelToState(GetShowLevel());
1435}
1436
1437// This should be the equivalent of GetStateMap, only the state strings
1438// are computed one at a time as needed.
1439QString VideoMetadata::GetState(const QString& name) const
1440{
1441 if (name == QStringLiteral(u"trailerstate"))
1442 return TrailerToState(GetTrailer());
1443 if (name == QStringLiteral(u"userratingstate"))
1444 return QString::number((int)(GetUserRating()));
1445 if (name == QStringLiteral(u"watchedstate"))
1446 return WatchedToState(GetWatched());
1447 if (name == QStringLiteral(u"videolevel"))
1449 return {};
1450}
1451
1453{
1454 m_imp->GetImageMap(imageMap);
1455}
1456
1457QString VideoMetadata::GetImage(const QString& name) const
1458{
1459 return m_imp->GetImage(name);
1460}
1461
1462void ClearMap(InfoMap &metadataMap)
1463{
1464 metadataMap["coverfile"] = "";
1465 metadataMap["screenshotfile"] = "";
1466 metadataMap["bannerfile"] = "";
1467 metadataMap["fanartfile"] = "";
1468 metadataMap["filename"] = "";
1469 metadataMap["sortfilename"] = "";
1470 metadataMap["title"] = "";
1471 metadataMap["sorttitle"] = "";
1472 metadataMap["subtitle"] = "";
1473 metadataMap["sortsubtitle"] = "";
1474 metadataMap["tagline"] = "";
1475 metadataMap["director"] = "";
1476 metadataMap["studio"] = "";
1477 metadataMap["description"] = "";
1478 metadataMap["description0"] = "";
1479 metadataMap["genres"] = "";
1480 metadataMap["countries"] = "";
1481 metadataMap["cast"] = "";
1482 metadataMap["rating"] = "";
1483 metadataMap["length"] = "";
1484 metadataMap["playcount"] = "";
1485 metadataMap["year"] = "";
1486 metadataMap["releasedate"] = "";
1487 metadataMap["userrating"] = "";
1488 metadataMap["season"] = "";
1489 metadataMap["episode"] = "";
1490 metadataMap["s##e##"] = "";
1491 metadataMap["##x##"] = "";
1492 metadataMap["trailerstate"] = "";
1493 metadataMap["userratingstate"] = "";
1494 metadataMap["watchedstate"] = "";
1495 metadataMap["videolevel"] = "";
1496 metadataMap["insertdate"] = "";
1497 metadataMap["inetref"] = "";
1498 metadataMap["homepage"] = "";
1499 metadataMap["child_id"] = "";
1500 metadataMap["browseable"] = "";
1501 metadataMap["watched"] = "";
1502 metadataMap["category"] = "";
1503 metadataMap["processed"] = "";
1504}
1505
1506QString VideoMetadata::MetadataGetTextCb(const QString& name, void *data)
1507{
1508 if (data == nullptr)
1509 return {};
1510 auto *metadata = static_cast<VideoMetadata *>(data);
1511 QString result = metadata->GetText(name);
1512 if (!result.isEmpty())
1513 return result;
1514 result = metadata->GetImage(name);
1515 if (!result.isEmpty())
1516 return result;
1517 return metadata->GetState(name);
1518}
1519
1520QString VideoMetadata::MetadataGetImageCb(const QString& name, void *data)
1521{
1522 if (data == nullptr)
1523 return {};
1524 auto *metadata = static_cast<VideoMetadata *>(data);
1525 return metadata->GetImage(name);
1526}
1527
1528QString VideoMetadata::MetadataGetStateCb(const QString& name, void *data)
1529{
1530 if (data == nullptr)
1531 return {};
1532 auto *metadata = static_cast<VideoMetadata *>(data);
1533 return metadata->GetState(name);
1534}
1535
1536const QString &VideoMetadata::GetPrefix() const
1537{
1538 return m_imp->GetPrefix();
1539}
1540
1542{
1544}
1545
1546const QString &VideoMetadata::GetTitle() const
1547{
1548 return m_imp->getTitle();
1549}
1550
1551const QString &VideoMetadata::GetSortTitle() const
1552{
1553 return m_imp->getSortTitle();
1554}
1555
1556void VideoMetadata::SetTitle(const QString &title, const QString &sortTitle)
1557{
1558 m_imp->SetTitle(title, sortTitle);
1559}
1560
1561const QString &VideoMetadata::GetSubtitle() const
1562{
1563 return m_imp->getSubtitle();
1564}
1565
1567{
1568 return m_imp->getSortSubtitle();
1569}
1570
1571void VideoMetadata::SetSubtitle(const QString &subtitle, const QString &sortSubtitle)
1572{
1573 m_imp->SetSubtitle(subtitle, sortSubtitle);
1574}
1575
1576const QString &VideoMetadata::GetTagline() const
1577{
1578 return m_imp->GetTagline();
1579}
1580
1581void VideoMetadata::SetTagline(const QString &tagline)
1582{
1583 m_imp->SetTagline(tagline);
1584}
1585
1587{
1588 return m_imp->getYear();
1589}
1590
1592{
1593 m_imp->SetYear(year);
1594}
1595
1597{
1598 return m_imp->getReleaseDate();
1599}
1600
1601void VideoMetadata::SetReleaseDate(QDate releasedate)
1602{
1603 m_imp->SetReleaseDate(releasedate);
1604}
1605
1606const QString &VideoMetadata::GetInetRef() const
1607{
1608 return m_imp->GetInetRef();
1609}
1610
1611void VideoMetadata::SetInetRef(const QString &inetRef)
1612{
1613 m_imp->SetInetRef(inetRef);
1614}
1615
1617{
1618 return m_imp->GetCollectionRef();
1619}
1620
1621void VideoMetadata::SetCollectionRef(int collectionref)
1622{
1623 m_imp->SetCollectionRef(collectionref);
1624}
1625
1626const QString &VideoMetadata::GetHomepage() const
1627{
1628 return m_imp->GetHomepage();
1629}
1630
1631void VideoMetadata::SetHomepage(const QString &homepage)
1632{
1633 m_imp->SetHomepage(homepage);
1634}
1635
1636const QString &VideoMetadata::GetDirector() const
1637{
1638 return m_imp->getDirector();
1639}
1640
1641void VideoMetadata::SetDirector(const QString &director)
1642{
1643 m_imp->SetDirector(director);
1644}
1645
1646const QString &VideoMetadata::GetStudio() const
1647{
1648 return m_imp->getStudio();
1649}
1650
1651void VideoMetadata::SetStudio(const QString &studio)
1652{
1653 m_imp->SetStudio(studio);
1654}
1655
1656const QString &VideoMetadata::GetPlot() const
1657{
1658 return m_imp->getPlot();
1659}
1660
1661void VideoMetadata::SetPlot(const QString &plot)
1662{
1663 m_imp->SetPlot(plot);
1664}
1665
1667{
1668 return m_imp->GetUserRating();
1669}
1670
1671void VideoMetadata::SetUserRating(float userRating)
1672{
1673 m_imp->SetUserRating(userRating);
1674}
1675
1676const QString &VideoMetadata::GetRating() const
1677{
1678 return m_imp->GetRating();
1679}
1680
1682{
1684}
1685
1686std::chrono::minutes VideoMetadata::GetLength() const
1687{
1688 return m_imp->GetLength();
1689}
1690
1691void VideoMetadata::SetLength(std::chrono::minutes length)
1692{
1693 m_imp->SetLength(length);
1694}
1695
1697{
1698 return m_imp->GetPlayCount();
1699}
1700
1702{
1703 m_imp->SetPlayCount(count);
1704}
1705
1707{
1708 return m_imp->GetSeason();
1709}
1710
1712{
1713 m_imp->SetSeason(season);
1714}
1715
1717{
1718 return m_imp->GetEpisode();
1719}
1720
1722{
1723 m_imp->SetEpisode(episode);
1724}
1725
1727{
1728 return m_imp->GetInsertdate();
1729}
1730
1732{
1733 m_imp->SetInsertdate(date);
1734}
1735
1736unsigned int VideoMetadata::GetID() const
1737{
1738 return m_imp->GetID();
1739}
1740
1742{
1743 m_imp->SetID(id);
1744}
1745
1747{
1748 return m_imp->GetChildID();
1749}
1750
1752{
1753 m_imp->SetChildID(childID);
1754}
1755
1757{
1758 return m_imp->GetBrowse();
1759}
1760
1762{
1763 m_imp->SetBrowse(browse);
1764}
1765
1767{
1768 return m_imp->GetWatched();
1769}
1770
1772{
1773 m_imp->SetWatched(watched);
1774}
1775
1777{
1778 return m_imp->GetProcessed();
1779}
1780
1782{
1783 m_imp->SetProcessed(processed);
1784}
1785
1787{
1788 return m_imp->GetContentType();
1789}
1790
1792{
1793 m_imp->SetContentType(contenttype);
1794}
1795
1796const QString &VideoMetadata::GetPlayCommand() const
1797{
1798 return m_imp->getPlayCommand();
1799}
1800
1801void VideoMetadata::SetPlayCommand(const QString &playCommand)
1802{
1803 m_imp->SetPlayCommand(playCommand);
1804}
1805
1807{
1808 return m_imp->GetShowLevel();
1809}
1810
1812{
1813 m_imp->SetShowLevel(showLevel);
1814}
1815
1816const QString &VideoMetadata::GetFilename() const
1817{
1818 return m_imp->getFilename();
1819}
1820
1822{
1823 return m_imp->getSortFilename();
1824}
1825
1826const QString &VideoMetadata::GetHash() const
1827{
1828 return m_imp->GetHash();
1829}
1830
1831void VideoMetadata::SetHash(const QString &hash)
1832{
1833 m_imp->SetHash(hash);
1834}
1835
1836const QString &VideoMetadata::GetHost() const
1837{
1838 return m_imp->GetHost();
1839}
1840
1841void VideoMetadata::SetHost(const QString &host)
1842{
1843 m_imp->SetHost(host);
1844}
1845
1846void VideoMetadata::SetFilename(const QString &filename, const QString &sortFilename)
1847{
1848 m_imp->SetFilename(filename, sortFilename);
1849}
1850
1851const QString &VideoMetadata::GetTrailer() const
1852{
1853 return m_imp->GetTrailer();
1854}
1855
1856void VideoMetadata::SetTrailer(const QString &trailer)
1857{
1858 m_imp->SetTrailer(trailer);
1859}
1860
1861const QString &VideoMetadata::GetCoverFile() const
1862{
1863 return m_imp->GetCoverFile();
1864}
1865
1866void VideoMetadata::SetCoverFile(const QString &coverFile)
1867{
1868 m_imp->SetCoverFile(coverFile);
1869}
1870
1871const QString &VideoMetadata::GetScreenshot() const
1872{
1873 return m_imp->GetScreenshot();
1874}
1875
1876void VideoMetadata::SetScreenshot(const QString &screenshot)
1877{
1878 m_imp->SetScreenshot(screenshot);
1879}
1880
1881const QString &VideoMetadata::GetBanner() const
1882{
1883 return m_imp->GetBanner();
1884}
1885
1886void VideoMetadata::SetBanner(const QString &banner)
1887{
1888 m_imp->SetBanner(banner);
1889}
1890
1891const QString &VideoMetadata::GetFanart() const
1892{
1893 return m_imp->GetFanart();
1894}
1895
1896void VideoMetadata::SetFanart(const QString &fanart)
1897{
1898 m_imp->SetFanart(fanart);
1899}
1900
1901const QString &VideoMetadata::GetCategory() const
1902{
1903 return m_imp->GetCategory();
1904}
1905
1906//void VideoMetadata::SetCategory(const QString &category)
1907//{
1908// m_imp->SetCategory(category);
1909//}
1910
1912{
1913 return m_imp->getGenres();
1914}
1915
1917{
1918 m_imp->SetGenres(genres);
1919}
1920
1922{
1923 return m_imp->GetCast();
1924}
1925
1927{
1928 m_imp->SetCast(cast);
1929}
1930
1932{
1933 return m_imp->GetCountries();
1934}
1935
1937{
1938 m_imp->SetCountries(countries);
1939}
1940
1942{
1943 return m_imp->GetCategoryID();
1944}
1945
1947{
1948 m_imp->SetCategoryID(id);
1949}
1950
1952{
1954}
1955
1957{
1959}
1960
1962{
1963 return m_imp->DeleteFromDatabase();
1964}
1965
1966#if 0
1967bool VideoMetadata::fillDataFromID(const VideoMetadataListManager &cache)
1968{
1969 if (m_imp->getID() == 0)
1970 return false;
1971
1973 if (mp.get())
1974 {
1975 *this = *mp;
1976 return true;
1977 }
1978
1979 return false;
1980}
1981#endif
1982
1984{
1985 if (m_imp->getFilename().isEmpty())
1986 return false;
1987
1989 cache.byFilename(m_imp->getFilename());
1990 if (mp)
1991 {
1992 *this = *mp;
1993 return true;
1994 }
1995
1996 return false;
1997}
1998
2000{
2001 return m_imp->DeleteFile();
2002}
2003
2005{
2006 m_imp->Reset();
2007}
2008
2010{
2011 return m_imp->IsHostSet();
2012}
2013
2015{
2016 return m_imp->sortBefore(rhs.m_imp);
2017}
2018
2020{
2021 return a.GetFilename() == b.GetFilename();
2022}
2023
2025{
2026 return a.GetFilename() != b.GetFilename();
2027}
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:129
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:839
QVariant value(int i) const
Definition: mythdbcon.h:205
bool isActive(void) const
Definition: mythdbcon.h:216
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
Definition: mythdbcon.cpp:904
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:620
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:890
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:814
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:552
int add(int id, int value)
Definition: dbaccess.cpp:451
bool get(int id, entry &values)
Definition: dbaccess.cpp:456
void remove(int id, int value)
Definition: dbaccess.cpp:461
bool IsThisHost(const QString &addr)
is this address mapped to this host
bool IsMasterBackend(void)
is this the actual MBE process
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:225
Level GetLevel() const
static QString GetFileHash(const QString &url)
Definition: remotefile.cpp:555
static bool DeleteFile(const QString &url)
Definition: remotefile.cpp:420
static bool Exists(const QString &url, struct stat *fileinfo)
Definition: remotefile.cpp:463
bool get(int id, QString &category)
Definition: dbaccess.cpp:221
int add(const QString &name)
Definition: dbaccess.cpp:216
QString FindFile(const QString &filename)
static QString generate_file_url(const QString &storage_group, const QString &host, const QString &path)
static VideoCastMap & getCastMap()
Definition: dbaccess.cpp:579
static VideoCast & GetCast()
Definition: dbaccess.cpp:535
static VideoCategory & GetCategory()
Definition: dbaccess.cpp:493
static VideoCountryMap & getCountryMap()
Definition: dbaccess.cpp:564
static VideoCountry & getCountry()
Definition: dbaccess.cpp:507
static VideoGenreMap & getGenreMap()
Definition: dbaccess.cpp:549
static VideoGenre & getGenre()
Definition: dbaccess.cpp:521
float GetUserRating() const
bool GetProcessed() const
const QString & getStudio() const
void SetHost(const QString &host)
void SetChildID(int childID)
void SetGenres(const genre_list &genres)
VideoMetadata::cast_list cast_list
const QString & GetHash() const
const QString & getPlot() const
unsigned int m_id
int GetSeason() const
const QString & GetTagline() const
QString GetImage(const QString &name) const
void SetWatched(bool watched)
void SetHash(const QString &hash)
int GetCategoryID() const
const cast_list & GetCast() const
const QString & getPlayCommand() const
void SetCategoryID(int id)
bool sortBefore(const VideoMetadataImp *rhs) const
Returns true if the object should appear before the argument.
void SetReleaseDate(QDate releasedate)
void SetShowLevel(ParentalLevel::Level showLevel)
void SetPlayCommand(const QString &playCommand)
const QString & GetPrefix() const
void SetStudio(const QString &studio)
bool GetWatched() const
void SetCast(const cast_list &cast)
bool IsHostSet() const
const QString & getDirector() const
void SetTrailer(const QString &trailer)
int getYear() const
void SetContentType(VideoContentType contenttype)
int GetEpisode() const
const QString & GetInetRef() const
const QString & GetHomepage() const
void SetYear(int year)
void ensureSortFields(void)
ParentalLevel::Level m_showlevel
const QString & getSortFilename() const
bool DeleteFile()
Deletes the file associated with a metadata entry.
void SetSeason(int season)
void fromDBRow(MSqlQuery &query)
Sets metadata from a DB row.
unsigned int GetPlayCount() const
VideoContentType GetContentType() const
int GetCollectionRef() const
VideoMetadata::country_list country_list
const QString & GetHost() const
std::chrono::minutes GetLength() const
const genre_list & getGenres() const
ParentalLevel::Level GetShowLevel() const
QDate getReleaseDate() const
const QString & GetRating() const
VideoMetadataImp(QString filename, QString sortFilename, QString hash, QString trailer, QString coverfile, QString screenshot, QString banner, QString fanart, const QString &title, QString sortTitle, const QString &subtitle, QString sortSubtitle, QString tagline, int year, const QDate releasedate, QString inetref, int collectionref, QString homepage, QString director, QString studio, QString plot, float userrating, QString rating, int length, int playcount, int season, int episode, const QDate insertdate, int id, ParentalLevel::Level showlevel, int categoryID, int childID, bool browse, bool watched, QString playcommand, QString category, genre_list genres, country_list countries, cast_list cast, QString host="", bool processed=false, VideoContentType contenttype=kContentUnknown)
void SetTagline(const QString &tagline)
void SetCollectionRef(int collectionref)
void SetDirector(const QString &director)
const QString & getTitle() const
const QString & GetScreenshot() const
void SetRating(const QString &rating)
void SetEpisode(int episode)
QDate GetInsertdate() const
VideoMetadataImp(const VideoMetadataImp &other)
const QString & GetBanner() const
const QString & GetCoverFile() const
void SetScreenshot(const QString &screenshot)
VideoMetadata::genre_list genre_list
void SetID(int id)
void SetTitle(const QString &title, const QString &sortTitle="")
void SetInsertdate(QDate date)
void SetFilename(const QString &filename, const QString &sortFilename="")
bool removeDir(const QString &dirName)
int GetChildID() const
void SetFanart(const QString &fanart)
void GetImageMap(InfoMap &imageMap) const
void SetPlot(const QString &plot)
void SetPrefix(const QString &prefix)
const QString & getFilename() const
void SetPlayCount(int playcount)
void SetInetRef(const QString &inetRef)
const QString & getSortTitle() const
const QString & GetFanart() const
void SetCountries(const country_list &countries)
VideoMetadataImp & operator=(const VideoMetadataImp &rhs)
const QString & GetTrailer() const
const QString & GetCategory() const
void SetBrowse(bool browse)
std::chrono::minutes m_length
void SetUserRating(float userRating)
const QString & getSubtitle() const
void SetLength(std::chrono::minutes length)
country_list m_countries
unsigned int GetID() const
void SetCoverFile(const QString &coverFile)
void SetHomepage(const QString &homepage)
bool GetBrowse() const
VideoContentType m_contenttype
void SetSubtitle(const QString &subtitle, const QString &sortSubtitle="")
VideoMetadataImp(MSqlQuery &query)
void SetBanner(const QString &banner)
void SetProcessed(bool processed)
const QString & getSortSubtitle() const
const country_list & GetCountries() const
VideoMetadataPtr byFilename(const QString &file_name) const
VideoMetadataPtr byID(unsigned int db_id) const
const QString & GetHost() const
void SetTrailer(const QString &trailer)
bool IsHostSet() const
void SetID(int id)
VideoMetadata(const QString &filename=QString(), const QString &sortFilename=QString(), const QString &hash=QString(), const QString &trailer=QString(), const QString &coverfile=QString(), const QString &screenshot=QString(), const QString &banner=QString(), const QString &fanart=QString(), const QString &title=QString(), const QString &sortTitle=QString(), const QString &subtitle=QString(), const QString &sortSubtitle=QString(), const QString &tagline=QString(), int year=VIDEO_YEAR_DEFAULT, QDate releasedate=QDate(), const QString &inetref=QString(), int collectionref=0, const QString &homepage=QString(), const QString &director=QString(), const QString &studio=QString(), const QString &plot=QString(), float userrating=0.0, const QString &rating=QString(), int length=0, int playcount=0, int season=0, int episode=0, QDate insertdate=QDate(), int id=0, ParentalLevel::Level showlevel=ParentalLevel::plLowest, int categoryID=0, int childID=-1, bool browse=true, bool watched=false, const QString &playcommand=QString(), const QString &category=QString(), const genre_list &genres=genre_list(), const country_list &countries=country_list(), const cast_list &cast=cast_list(), const QString &host="", bool processed=false, VideoContentType contenttype=kContentUnknown)
void SetInetRef(const QString &inetRef)
void SetGenres(const genre_list &genres)
bool GetProcessed() const
const QString & GetCoverFile() const
void SetCoverFile(const QString &coverFile)
const QString & GetCategory() const
int GetYear() const
void SetReleaseDate(QDate releasedate)
void SetCountries(const country_list &countries)
bool GetWatched() const
const QString & GetTitle() const
void SetHash(const QString &hash)
int GetCategoryID() const
void SetSubtitle(const QString &subtitle, const QString &sortSubtitle="")
const country_list & GetCountries() const
unsigned int GetPlayCount() const
const QString & GetSortFilename() const
const QString & GetStudio() const
VideoMetadata & operator=(const VideoMetadata &rhs)
void SetTagline(const QString &tagline)
void SetFanart(const QString &fanart)
void SetUserRating(float userRating)
class VideoMetadataImp * m_imp
static QString FilenameToMeta(const QString &file_name, int position)
void SetYear(int year)
unsigned int GetID() const
void SetFilename(const QString &filename, const QString &sortFilename="")
QString GetImage(const QString &name) const
void SetSeason(int season)
const QString & GetFanart() const
std::vector< cast_entry > cast_list
Definition: videometadata.h:34
void SetPlayCount(int count)
ParentalLevel::Level GetShowLevel() const
void SetStudio(const QString &studio)
void SetShowLevel(ParentalLevel::Level showLevel)
void SetEpisode(int episode)
void SetPlot(const QString &plot)
std::chrono::minutes GetLength() const
const QString & GetHash() const
void GetImageMap(InfoMap &imageMap)
int GetChildID() const
const cast_list & GetCast() const
const QString & GetInetRef() const
void SetChildID(int childID)
const QString & GetPrefix() const
const QString & GetBanner() const
bool sortBefore(const VideoMetadata &rhs) const
const QString & GetTrailer() const
const QString & GetRating() const
void SetTitle(const QString &title, const QString &sortTitle="")
const genre_list & GetGenres() const
const QString & GetDirector() const
static QString VideoFileHash(const QString &file_name, const QString &host)
void SetCategoryID(int id)
void SetCollectionRef(int collectionref)
static QString MetadataGetStateCb(const QString &name, void *data)
void SetBrowse(bool browse)
const QString & GetSortTitle() const
void SetProcessed(bool processed)
void GetStateMap(InfoMap &stateMap) const
void SetContentType(VideoContentType contenttype)
void toMap(InfoMap &metadataMap)
void SetLength(std::chrono::minutes length)
bool GetBrowse() const
void SetCast(const cast_list &cast)
const QString & GetScreenshot() const
QDate GetInsertdate() const
static int UpdateHashedDBRecord(const QString &hash, const QString &file_name, const QString &host)
void SetPrefix(const QString &prefix)
void SetDirector(const QString &director)
const QString & GetSubtitle() const
void SetScreenshot(const QString &screenshot)
const QString & GetSortSubtitle() const
QString GetText(const QString &name) const
const QString & GetTagline() const
bool FillDataFromFilename(const VideoMetadataListManager &cache)
void SetInsertdate(QDate date)
int GetSeason() const
void SetRating(const QString &rating)
std::vector< genre_entry > genre_list
Definition: videometadata.h:32
QString GetState(const QString &name) const
int GetCollectionRef() const
bool DeleteFromDatabase()
void SetHomepage(const QString &homepage)
QDate GetReleaseDate() const
const QString & GetPlayCommand() const
static QString MetadataGetTextCb(const QString &name, void *data)
const QString & GetHomepage() const
void SetBanner(const QString &banner)
std::vector< country_entry > country_list
Definition: videometadata.h:33
void SetPlayCommand(const QString &playCommand)
void SetWatched(bool watched)
void SetHost(const QString &host)
VideoContentType GetContentType() const
static QString MetadataGetImageCb(const QString &name, void *data)
const QString & GetPlot() const
int GetEpisode() const
const QString & GetFilename() const
float GetUserRating() const
void Reset()
Resets to default metadata.
T * get() const
Definition: quicksp.h:73
const QString VIDEO_INETREF_DEFAULT
Definition: globals.cpp:24
const QString VIDEO_PLOT_DEFAULT
Definition: globals.cpp:32
const QString VIDEO_TRAILER_DEFAULT
Definition: globals.cpp:26
const QString VIDEO_BANNER_DEFAULT
Definition: globals.cpp:28
const QString VIDEO_SCREENSHOT_DEFAULT
Definition: globals.cpp:27
const QString VIDEO_FANART_DEFAULT
Definition: globals.cpp:29
const QString VIDEO_RATING_DEFAULT
Definition: globals.cpp:30
const QString VIDEO_DIRECTOR_UNKNOWN
Definition: globals.cpp:9
const QString VIDEO_DIRECTOR_DEFAULT
Definition: globals.cpp:23
const QString VIDEO_COVERFILE_DEFAULT
Definition: globals.cpp:25
static const iso6937table * d
VideoContentType
@ kContentTelevision
@ kContentUnknown
@ kContentMovie
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
QString FileHash(const QString &filename)
std::shared_ptr< MythSortHelper > getMythSortHelper(void)
Get a pointer to the MythSortHelper singleton.
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
@ kDateFull
Default local time.
Definition: mythdate.h:20
@ kAddYear
Add year to string if not included.
Definition: mythdate.h:26
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:39
MBASE_PUBLIC std::strong_ordering naturalCompare(const QString &_a, const QString &_b, Qt::CaseSensitivity caseSensitivity=Qt::CaseSensitive)
This method chops the input a and b into pieces of digits and non-digits (a1.05 becomes a | 1 | .
Definition: stringutil.cpp:122
QString intToPaddedString(int n, int width=2)
Creates a zero padded string representation of an integer.
Definition: stringutil.h:32
QString eatBraces(const QString &title, const QString &left_brace, const QString &right_brace)
def rating(profile, smoonURL, gate)
Definition: scan.py:36
values_type values
Definition: dbaccess.h:44
bool operator!=(const VideoMetadata &a, const VideoMetadata &b)
bool operator==(const VideoMetadata &a, const VideoMetadata &b)
void ClearMap(InfoMap &metadataMap)
static constexpr uint16_t VIDEO_YEAR_DEFAULT
Definition: videometadata.h:18
QString ParentalLevelToState(const ParentalLevel &level)
Definition: videoutils.cpp:239
QString GetDisplayUserRating(float userrating)
Definition: videoutils.cpp:151
QString WatchedToState(bool watched)
Definition: videoutils.cpp:273
QString GetDisplayProcessed(bool processed)
Definition: videoutils.cpp:188
QString TrailerToState(const QString &trailerFile)
Definition: videoutils.cpp:263
QString GetDisplayRating(const QString &rating)
Definition: videoutils.cpp:211
QString GetDisplayWatched(bool watched)
Definition: videoutils.cpp:176
VideoContentType ContentTypeFromString(const QString &type)
Definition: videoutils.cpp:283
QString ContentTypeToString(VideoContentType type)
Definition: videoutils.cpp:301
bool IsDefaultCoverFile(const QString &coverfile)
Definition: videoutils.cpp:127
QString GetDisplayCountries(const VideoMetadata &item)
Definition: videoutils.cpp:225
QStringList GetDisplayCast(const VideoMetadata &item)
Definition: videoutils.cpp:232
QString GetDisplayLength(std::chrono::minutes length)
Definition: videoutils.cpp:156
QString GetDisplayYear(int year)
Definition: videoutils.cpp:206
QString GetDisplayGenres(const VideoMetadata &item)
Definition: videoutils.cpp:218
QString GetDisplayBrowse(bool browse)
Definition: videoutils.cpp:164