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