MythTV  0.26-pre
videometadata.cpp
Go to the documentation of this file.
00001 #include <cmath> // for isnan()
00002 
00003 #include <QFile>
00004 #include <QDir>
00005 #include <QFileInfo>
00006 #include <QRegExp>
00007 
00008 #include "mythcorecontext.h"
00009 #include "mythcontext.h"
00010 #include "mythdb.h"
00011 #include "storagegroup.h"
00012 #include "remotefile.h"
00013 #include "remoteutil.h"
00014 #include "mythmiscutil.h"
00015 #include "mythlogging.h"
00016 #include "globals.h"
00017 #include "dbaccess.h"
00018 #include "videometadatalistmanager.h"
00019 #include "videoutils.h"
00020 #include "netutils.h"
00021 
00022 struct SortData
00023 {
00024     SortData(const QString &title, const QString &filename, const QString &id) :
00025         m_title(title), m_filename(filename), m_id(id)
00026     {
00027     }
00028 
00029     QString m_title;
00030     QString m_filename;
00031     QString m_id;
00032 };
00033 
00034 static bool operator<(const SortData &lhs, const SortData &rhs)
00035 {
00036     int ret = QString::localeAwareCompare(lhs.m_title, rhs.m_title);
00037 
00038     if (ret == 0)
00039         ret = QString::localeAwareCompare(lhs.m_filename, rhs.m_filename);
00040 
00041     if (ret == 0)
00042         ret = QString::localeAwareCompare(lhs.m_id, rhs.m_id);
00043 
00044     return ret < 0;
00045 }
00046 
00047 VideoMetadata::SortKey::SortKey() : m_sd(0)
00048 {
00049 }
00050 
00051 VideoMetadata::SortKey::SortKey(const SortData &data)
00052 {
00053     m_sd = new SortData(data);
00054 }
00055 
00056 VideoMetadata::SortKey::SortKey(const SortKey &other)
00057 {
00058     *this = other;
00059 }
00060 
00061 VideoMetadata::SortKey &VideoMetadata::SortKey::operator=(const SortKey &rhs)
00062 {
00063     if (this != &rhs)
00064     {
00065         Clear();
00066         if (rhs.m_sd)
00067             m_sd = new SortData(*rhs.m_sd);
00068     }
00069 
00070     return *this;
00071 }
00072 
00073 VideoMetadata::SortKey::~SortKey()
00074 {
00075     Clear();
00076 }
00077 
00078 bool VideoMetadata::SortKey::isSet() const
00079 {
00080     return m_sd != 0;
00081 }
00082 
00083 void VideoMetadata::SortKey::Clear()
00084 {
00085     delete m_sd;
00086     m_sd = 0;
00087 }
00088 
00089 class VideoMetadataImp
00090 {
00091   public:
00092     typedef VideoMetadata::genre_list genre_list;
00093     typedef VideoMetadata::country_list country_list;
00094     typedef VideoMetadata::cast_list cast_list;
00095 
00096   public:
00097     VideoMetadataImp(const QString &filename, const QString &hash, const QString &trailer,
00098              const QString &coverfile, const QString &screenshot, const QString &banner,
00099              const QString &fanart, const QString &title, const QString &subtitle,
00100              const QString &tagline, int year, const QDate &releasedate,
00101              const QString &inetref, int collectionref, const QString &homepage,
00102              const QString &director, const QString &studio,
00103              const QString &plot, float userrating,
00104              const QString &rating, int length, int playcount,
00105              int season, int episode, const QDate &insertdate,
00106              int id, ParentalLevel::Level showlevel, int categoryID,
00107              int childID, bool browse, bool watched,
00108              const QString &playcommand, const QString &category,
00109              const genre_list &genres,
00110              const country_list &countries,
00111              const cast_list &cast,
00112              const QString &host = "",
00113              bool processed = false,
00114              VideoContentType contenttype = kContentUnknown) :
00115         m_title(title), m_subtitle(subtitle), m_tagline(tagline),
00116         m_inetref(inetref), m_collectionref(collectionref), m_homepage(homepage),
00117         m_director(director), m_studio(studio),
00118         m_plot(plot), m_rating(rating), m_playcommand(playcommand), m_category(category),
00119         m_genres(genres), m_countries(countries), m_cast(cast),
00120         m_filename(filename), m_hash(hash), m_trailer(trailer), m_coverfile(coverfile),
00121         m_screenshot(screenshot), m_banner(banner), m_fanart(fanart),
00122         m_host(host), m_categoryID(categoryID), m_childID(childID),
00123         m_year(year), m_releasedate(releasedate), m_length(length), m_playcount(playcount),
00124         m_season(season), m_episode(episode), m_insertdate(insertdate), m_showlevel(showlevel),
00125         m_browse(browse), m_watched(watched), m_id(id),
00126         m_userrating(userrating), m_processed(processed),
00127         m_contenttype(contenttype)
00128     {
00129         VideoCategory::GetCategory().get(m_categoryID, m_category);
00130     }
00131 
00132     VideoMetadataImp(MSqlQuery &query)
00133     {
00134         fromDBRow(query);
00135     }
00136 
00137     VideoMetadataImp(const VideoMetadataImp &other)
00138     {
00139         *this = other;
00140     }
00141 
00142     VideoMetadataImp &operator=(const VideoMetadataImp &rhs)
00143     {
00144         if (this != &rhs)
00145         {
00146             m_title = rhs.m_title;
00147             m_subtitle = rhs.m_subtitle;
00148             m_tagline = rhs.m_tagline;
00149             m_inetref = rhs.m_inetref;
00150             m_collectionref = rhs.m_collectionref;
00151             m_homepage = rhs.m_homepage;
00152             m_director = rhs.m_director;
00153             m_studio = rhs.m_studio;
00154             m_plot = rhs.m_plot;
00155             m_rating = rhs.m_rating;
00156             m_playcommand = rhs.m_playcommand;
00157             m_category = rhs.m_category;
00158             m_genres = rhs.m_genres;
00159             m_countries = rhs.m_countries;
00160             m_cast = rhs.m_cast;
00161             m_filename = rhs.m_filename;
00162             m_hash = rhs.m_hash;
00163             m_trailer = rhs.m_trailer;
00164             m_coverfile = rhs.m_coverfile;
00165             m_screenshot = rhs.m_screenshot;
00166             m_banner = rhs.m_banner;
00167             m_fanart = rhs.m_fanart;
00168 
00169             m_categoryID = rhs.m_categoryID;
00170             m_childID = rhs.m_childID;
00171             m_year = rhs.m_year;
00172             m_releasedate = rhs.m_releasedate;
00173             m_length = rhs.m_length;
00174             m_playcount = rhs.m_playcount;
00175             m_season = rhs.m_season;
00176             m_episode = rhs.m_episode;
00177             m_insertdate = rhs.m_insertdate;
00178             m_showlevel = rhs.m_showlevel;
00179             m_browse = rhs.m_browse;
00180             m_watched = rhs.m_watched;
00181             m_id = rhs.m_id;
00182             m_userrating = rhs.m_userrating;
00183             m_host = rhs.m_host;
00184             m_processed = rhs.m_processed;
00185             m_contenttype = rhs.m_contenttype;
00186 
00187             // No DB vars
00188             m_sort_key = rhs.m_sort_key;
00189             m_prefix = rhs.m_prefix;
00190         }
00191 
00192         return *this;
00193     }
00194 
00195   public:
00196     bool HasSortKey() const { return m_sort_key.isSet(); }
00197     const VideoMetadata::SortKey &GetSortKey() const { return m_sort_key; }
00198     void SetSortKey(const VideoMetadata::SortKey &sort_key)
00199     {
00200         m_sort_key = sort_key;
00201     }
00202 
00203     const QString &GetPrefix() const { return m_prefix; }
00204     void SetPrefix(const QString &prefix) { m_prefix = prefix; }
00205 
00206     const QString &getTitle() const { return m_title; }
00207     void SetTitle(const QString& title)
00208     {
00209         if (gCoreContext->HasGUI())
00210             m_sort_key.Clear();
00211         m_title = title;
00212     }
00213 
00214     const QString &getSubtitle() const { return m_subtitle; }
00215     void SetSubtitle(const QString &subtitle) { m_subtitle = subtitle; }
00216 
00217     const QString &GetTagline() const { return m_tagline; }
00218     void SetTagline(const QString &tagline) { m_tagline = tagline; }
00219 
00220     const QString &GetInetRef() const { return m_inetref; }
00221     void SetInetRef(const QString &inetRef) { m_inetref = inetRef; }
00222 
00223     int GetCollectionRef() const { return m_collectionref; }
00224     void SetCollectionRef(int collectionref) { m_collectionref = collectionref; }
00225 
00226     const QString &GetHomepage() const { return m_homepage; }
00227     void SetHomepage(const QString &homepage) { m_homepage = homepage; }
00228 
00229     const QString &getDirector() const { return m_director; }
00230     void SetDirector(const QString &director) { m_director = director; }
00231 
00232     const QString &getStudio() const { return m_studio; }
00233     void SetStudio(const QString &studio) { m_studio = studio; }
00234 
00235     const QString &getPlot() const { return m_plot; }
00236     void SetPlot(const QString &plot) { m_plot = plot; }
00237 
00238     const QString &GetRating() const { return m_rating; }
00239     void SetRating(const QString &rating) { m_rating = rating; }
00240 
00241     const QString &getPlayCommand() const { return m_playcommand; }
00242     void SetPlayCommand(const QString &playCommand)
00243     {
00244         m_playcommand = playCommand;
00245     }
00246 
00247     const QString &GetCategory() const { return m_category; }
00248 //    void SetCategory(const QString &category) { m_category = category; }
00249 
00250     const genre_list &getGenres() const { return m_genres; }
00251     void SetGenres(const genre_list &genres) { m_genres = genres; }
00252 
00253     const country_list &GetCountries() const { return m_countries; }
00254     void SetCountries(const country_list &countries)
00255     {
00256         m_countries = countries;
00257     }
00258 
00259     const cast_list &GetCast() const { return m_cast; }
00260     void SetCast(const cast_list &cast) { m_cast = cast; }
00261 
00262     const QString &GetHost() const { return m_host; }
00263     void SetHost(const QString &host) { m_host = host; }
00264 
00265     const QString &getFilename() const { return m_filename; }
00266     void SetFilename(const QString &filename) { m_filename = filename; }
00267 
00268     const QString &GetHash() const { return m_hash; }
00269     void SetHash(const QString &hash) { m_hash = hash; }
00270 
00271     const QString &GetTrailer() const { return m_trailer; }
00272     void SetTrailer(const QString &trailer) { m_trailer = trailer; }
00273 
00274     const QString &GetCoverFile() const { return m_coverfile; }
00275     void SetCoverFile(const QString &coverFile) { m_coverfile = coverFile; }
00276 
00277     const QString &GetScreenshot() const { return m_screenshot; }
00278     void SetScreenshot(const QString &screenshot) { m_screenshot = screenshot; }
00279 
00280     const QString &GetBanner() const { return m_banner; }
00281     void SetBanner(const QString &banner) { m_banner = banner; }
00282 
00283     const QString &GetFanart() const { return m_fanart; }
00284     void SetFanart(const QString &fanart) { m_fanart = fanart; }
00285 
00286     int GetCategoryID() const
00287     {
00288         return m_categoryID;
00289     }
00290     void SetCategoryID(int id);
00291 
00292     int GetChildID() const { return m_childID; }
00293     void SetChildID(int childID) { m_childID = childID; }
00294 
00295     int getYear() const { return m_year; }
00296     void SetYear(int year) { m_year = year; }
00297 
00298     QDate getReleaseDate() const { return m_releasedate; }
00299     void SetReleaseDate(QDate releasedate) { m_releasedate = releasedate; }
00300 
00301     int GetLength() const { return m_length; }
00302     void SetLength(int length) { m_length = length; }
00303 
00304     unsigned int GetPlayCount() const { return m_playcount; }
00305     void SetPlayCount(int playcount) { m_playcount = playcount; }
00306 
00307     int GetSeason() const { return m_season; }
00308     void SetSeason(int season) { m_season = season; }
00309 
00310     int GetEpisode() const { return m_episode; }
00311     void SetEpisode(int episode) { m_episode = episode; }
00312 
00313     QDate GetInsertdate() const { return m_insertdate;}
00314     void SetInsertdate(QDate date) { m_insertdate = date;}
00315 
00316     ParentalLevel::Level GetShowLevel() const { return m_showlevel; }
00317     void SetShowLevel(ParentalLevel::Level showLevel)
00318     {
00319         m_showlevel = ParentalLevel(showLevel).GetLevel();
00320     }
00321 
00322     bool GetBrowse() const { return m_browse; }
00323     void SetBrowse(bool browse) { m_browse = browse; }
00324 
00325     bool GetWatched() const { return m_watched; }
00326     void SetWatched(bool watched) { m_watched = watched; }
00327 
00328     unsigned int GetID() const { return m_id; }
00329     void SetID(int id) { m_id = id; }
00330 
00331     float GetUserRating() const { return m_userrating; }
00332     void SetUserRating(float userRating) { m_userrating = userRating; }
00333 
00334     bool GetProcessed() const { return m_processed; }
00335     void SetProcessed(bool processed) { m_processed = processed; }
00336 
00337     VideoContentType GetContentType() const { return m_contenttype; }
00338     void SetContentType(VideoContentType contenttype) { m_contenttype = contenttype; }
00339 
00341 
00342     void SaveToDatabase();
00343     void UpdateDatabase();
00344     bool DeleteFromDatabase();
00345 
00346     bool DeleteFile();
00347 
00348     void Reset();
00349 
00350     bool IsHostSet() const;
00351 
00352   private:
00353     void fillCountries();
00354     void updateCountries();
00355     void fillGenres();
00356     void fillCast();
00357     void updateGenres();
00358     void updateCast();
00359     bool removeDir(const QString &dirName);
00360     void fromDBRow(MSqlQuery &query);
00361     void saveToDatabase();
00362 
00363   private:
00364     QString m_title;
00365     QString m_subtitle;
00366     QString m_tagline;
00367     QString m_inetref;
00368     int m_collectionref;
00369     QString m_homepage;
00370     QString m_director;
00371     QString m_studio;
00372     QString m_plot;
00373     QString m_rating;
00374     QString m_playcommand;
00375     QString m_category;
00376     genre_list m_genres;
00377     country_list m_countries;
00378     cast_list m_cast;
00379     QString m_filename;
00380     QString m_hash;
00381     QString m_trailer;
00382     QString m_coverfile;
00383     QString m_screenshot;
00384     QString m_banner;
00385     QString m_fanart;
00386     QString m_host;
00387 
00388     int m_categoryID;
00389     int m_childID;
00390     int m_year;
00391     QDate m_releasedate;
00392     int m_length;
00393     int m_playcount;
00394     int m_season;
00395     int m_episode;
00396     QDate m_insertdate;
00397     ParentalLevel::Level m_showlevel;
00398     bool m_browse;
00399     bool m_watched;
00400     unsigned int m_id;  // videometadata.intid
00401     float m_userrating;
00402     bool m_processed;
00403     VideoContentType m_contenttype;
00404 
00405     // not in DB
00406     VideoMetadata::SortKey m_sort_key;
00407     QString m_prefix;
00408 };
00409 
00413 bool VideoMetadataImp::removeDir(const QString &dirName)
00414 {
00415     QDir d(dirName);
00416 
00417     QFileInfoList contents = d.entryInfoList();
00418     if (!contents.size())
00419     {
00420         return d.rmdir(dirName);
00421     }
00422 
00423     for (QFileInfoList::iterator p = contents.begin(); p != contents.end(); ++p)
00424     {
00425         if (p->fileName() == "." ||
00426             p->fileName() == "..")
00427         {
00428             continue;
00429         }
00430         if (p->isDir())
00431         {
00432             QString fileName = p->fileName();
00433             if (!removeDir(fileName))
00434                 return false;
00435         }
00436         else
00437         {
00438             if (!QFile(p->fileName()).remove())
00439                 return false;
00440         }
00441     }
00442     return d.rmdir(dirName);
00443 }
00444 
00446 bool VideoMetadataImp::DeleteFile()
00447 {
00448     bool isremoved = false;
00449 
00450     if (!m_host.isEmpty())
00451     {
00452         QString url = generate_file_url("Videos", m_host, m_filename);
00453         isremoved = RemoteFile::DeleteFile(url);
00454     }
00455     else
00456     {
00457         QFileInfo fi(m_filename);
00458         if (fi.isDir())
00459         {
00460             isremoved = removeDir(m_filename);
00461         }
00462         else
00463         {
00464             isremoved = QFile::remove(m_filename);
00465         }
00466     }
00467 
00468     if (!isremoved)
00469     {
00470         LOG(VB_GENERAL, LOG_DEBUG, QString("Could not delete file: %1")
00471                                        .arg(m_filename));
00472     }
00473 
00474     return isremoved;
00475 }
00476 
00477 void VideoMetadataImp::Reset()
00478 {
00479     VideoMetadataImp tmp(m_filename, VideoMetadata::VideoFileHash(m_filename, m_host), VIDEO_TRAILER_DEFAULT,
00480                     VIDEO_COVERFILE_DEFAULT, VIDEO_SCREENSHOT_DEFAULT, VIDEO_BANNER_DEFAULT,
00481                     VIDEO_FANART_DEFAULT, VideoMetadata::FilenameToMeta(m_filename, 1), QString(),
00482                     VideoMetadata::FilenameToMeta(m_filename, 4), VIDEO_YEAR_DEFAULT,
00483                     QDate(), VIDEO_INETREF_DEFAULT, -1, QString(), VIDEO_DIRECTOR_DEFAULT,
00484                     QString(), VIDEO_PLOT_DEFAULT, 0.0,
00485                     VIDEO_RATING_DEFAULT, 0, 0,
00486                     VideoMetadata::FilenameToMeta(m_filename, 2).toInt(),
00487                     VideoMetadata::FilenameToMeta(m_filename, 3).toInt(), QDate(), m_id,
00488                     ParentalLevel::plLowest, 0, -1, true, false, "", "",
00489                     VideoMetadata::genre_list(), VideoMetadata::country_list(),
00490                     VideoMetadata::cast_list(), m_host, false);
00491     tmp.m_prefix = m_prefix;
00492 
00493     *this = tmp;
00494 }
00495 
00496 bool VideoMetadataImp::IsHostSet() const
00497 {
00498     return !m_host.isEmpty();
00499 }
00500 
00501 void VideoMetadataImp::fillGenres()
00502 {
00503     m_genres.clear();
00504     VideoGenreMap &vgm = VideoGenreMap::getGenreMap();
00505     VideoGenreMap::entry genres;
00506     if (vgm.get(m_id, genres))
00507     {
00508         VideoGenre &vg = VideoGenre::getGenre();
00509         for (VideoGenreMap::entry::values_type::const_iterator p =
00510              genres.values.begin(); p != genres.values.end(); ++p)
00511         {
00512             // Just add empty string for no-name genres
00513             QString name;
00514             vg.get(*p, name);
00515             m_genres.push_back(genre_list::value_type(*p, name));
00516         }
00517     }
00518 }
00519 
00520 void VideoMetadataImp::fillCountries()
00521 {
00522     m_countries.clear();
00523     VideoCountryMap &vcm = VideoCountryMap::getCountryMap();
00524     VideoCountryMap::entry countries;
00525     if (vcm.get(m_id, countries))
00526     {
00527         VideoCountry &vc = VideoCountry::getCountry();
00528         for (VideoCountryMap::entry::values_type::const_iterator p =
00529              countries.values.begin(); p != countries.values.end(); ++p)
00530         {
00531             // Just add empty string for no-name countries
00532             QString name;
00533             vc.get(*p, name);
00534             m_countries.push_back(country_list::value_type(*p, name));
00535         }
00536     }
00537 }
00538 
00539 void VideoMetadataImp::fillCast()
00540 {
00541     m_cast.clear();
00542     VideoCastMap &vcm = VideoCastMap::getCastMap();
00543     VideoCastMap::entry cast;
00544     if (vcm.get(m_id, cast))
00545     {
00546         VideoCast &vc = VideoCast::GetCast();
00547         for (VideoCastMap::entry::values_type::const_iterator p =
00548              cast.values.begin(); p != cast.values.end(); ++p)
00549         {
00550             // Just add empty string for no-name cast
00551             QString name;
00552             vc.get(*p, name);
00553             m_cast.push_back(cast_list::value_type(*p, name));
00554         }
00555     }
00556 }
00557 
00559 void VideoMetadataImp::fromDBRow(MSqlQuery &query)
00560 {
00561     m_title = query.value(0).toString();
00562     m_director = query.value(1).toString();
00563     m_studio = query.value(2).toString();
00564     m_plot = query.value(3).toString();
00565     m_rating = query.value(4).toString();
00566     m_year = query.value(5).toInt();
00567     m_releasedate = query.value(6).toDate();
00568     m_userrating = (float)query.value(7).toDouble();
00569     if (isnan(m_userrating) || m_userrating < 0)
00570         m_userrating = 0.0;
00571     if (m_userrating > 10.0)
00572         m_userrating = 10.0;
00573     m_length = query.value(8).toInt();
00574     m_playcount = query.value(9).toInt();
00575     m_filename = query.value(10).toString();
00576     m_hash = query.value(11).toString();
00577     m_showlevel = ParentalLevel(query.value(12).toInt()).GetLevel();
00578     m_coverfile = query.value(13).toString();
00579     m_inetref = query.value(14).toString();
00580     m_collectionref = query.value(15).toUInt();
00581     m_homepage = query.value(16).toString();
00582     m_childID = query.value(17).toUInt();
00583     m_browse = query.value(18).toBool();
00584     m_watched = query.value(19).toBool();
00585     m_playcommand = query.value(20).toString();
00586     m_categoryID = query.value(21).toInt();
00587     m_id = query.value(22).toInt();
00588     m_trailer = query.value(23).toString();
00589     m_screenshot = query.value(24).toString();
00590     m_banner = query.value(25).toString();
00591     m_fanart = query.value(26).toString();
00592     m_subtitle = query.value(27).toString();
00593     m_tagline = query.value(28).toString();
00594     m_season = query.value(29).toInt();
00595     m_episode = query.value(30).toInt();
00596     m_host = query.value(31).toString();
00597     m_insertdate = query.value(32).toDate();
00598     m_processed = query.value(33).toBool();
00599 
00600     m_contenttype = ContentTypeFromString(query.value(34).toString());
00601 
00602     VideoCategory::GetCategory().get(m_categoryID, m_category);
00603 
00604     // Genres
00605     fillGenres();
00606 
00607     //Countries
00608     fillCountries();
00609 
00610     // Cast
00611     fillCast();
00612 }
00613 
00614 void VideoMetadataImp::saveToDatabase()
00615 {
00616     if (m_title.isEmpty())
00617         m_title = VideoMetadata::FilenameToMeta(m_filename, 1);
00618     if (m_hash.isEmpty())
00619         m_hash = VideoMetadata::VideoFileHash(m_filename, m_host);
00620     if (m_subtitle.isEmpty())
00621         m_subtitle = VideoMetadata::FilenameToMeta(m_filename, 4);
00622     if (m_director.isEmpty())
00623         m_director = VIDEO_DIRECTOR_UNKNOWN;
00624     if (m_plot.isEmpty())
00625         m_plot = VIDEO_PLOT_DEFAULT;
00626     if (m_rating.isEmpty())
00627         m_rating = VIDEO_RATING_DEFAULT;
00628     if (m_coverfile.isEmpty())
00629         m_coverfile = VIDEO_COVERFILE_DEFAULT;
00630     if (m_screenshot.isEmpty())
00631         m_screenshot = VIDEO_SCREENSHOT_DEFAULT;
00632     if (m_banner.isEmpty())
00633         m_banner = VIDEO_BANNER_DEFAULT;
00634     if (m_fanart.isEmpty())
00635         m_fanart = VIDEO_FANART_DEFAULT;
00636     if (m_trailer.isEmpty())
00637         m_trailer = VIDEO_TRAILER_DEFAULT;
00638     if (m_inetref.isEmpty())
00639         m_inetref = VIDEO_INETREF_DEFAULT;
00640     if (isnan(m_userrating))
00641         m_userrating = 0.0;
00642     if (m_userrating < -10.0 || m_userrating > 10.0)
00643         m_userrating = 0.0;
00644     if (m_releasedate.toString().isEmpty())
00645         m_releasedate = QDate::fromString("0000-00-00", "YYYY-MM-DD");
00646     if (m_contenttype == kContentUnknown)
00647     {
00648         if (m_season > 0 || m_episode > 0)
00649             m_contenttype = kContentTelevision;
00650         else
00651             m_contenttype = kContentMovie;
00652     }
00653 
00654     bool inserting = m_id == 0;
00655 
00656     MSqlQuery query(MSqlQuery::InitCon());
00657 
00658     if (inserting)
00659     {
00660         m_browse = 1;
00661 
00662         m_watched = 0;
00663 
00664         query.prepare("INSERT INTO videometadata (title,subtitle,tagline,director,studio,plot,"
00665                       "rating,year,userrating,length,season,episode,filename,hash,"
00666                       "showlevel,coverfile,inetref,homepage,browse,watched,trailer,"
00667                       "screenshot,banner,fanart,host,processed,contenttype) VALUES (:TITLE, :SUBTITLE, "
00668                       ":TAGLINE, :DIRECTOR, :STUDIO, :PLOT, :RATING, :YEAR, :USERRATING, "
00669                       ":LENGTH, :SEASON, :EPISODE, :FILENAME, :HASH, :SHOWLEVEL, "
00670                       ":COVERFILE, :INETREF, :HOMEPAGE, :BROWSE, :WATCHED, "
00671                       ":TRAILER, :SCREENSHOT, :BANNER, :FANART, :HOST, :PROCESSED, :CONTENTTYPE)");
00672     }
00673     else
00674     {
00675         query.prepare("UPDATE videometadata SET title = :TITLE, subtitle = :SUBTITLE, "
00676                       "tagline = :TAGLINE, director = :DIRECTOR, studio = :STUDIO, "
00677                       "plot = :PLOT, rating= :RATING, year = :YEAR, "
00678                       "releasedate = :RELEASEDATE, userrating = :USERRATING, "
00679                       "length = :LENGTH, playcount = :PLAYCOUNT, season = :SEASON, "
00680                       "episode = :EPISODE, filename = :FILENAME, hash = :HASH, trailer = :TRAILER, "
00681                       "showlevel = :SHOWLEVEL, coverfile = :COVERFILE, "
00682                       "screenshot = :SCREENSHOT, banner = :BANNER, fanart = :FANART, "
00683                       "inetref = :INETREF, collectionref = :COLLECTION, homepage = :HOMEPAGE, "
00684                       "browse = :BROWSE, watched = :WATCHED, host = :HOST, playcommand = :PLAYCOMMAND, "
00685                       "childid = :CHILDID, category = :CATEGORY, processed = :PROCESSED, "
00686                       "contenttype = :CONTENTTYPE WHERE intid = :INTID");
00687 
00688         query.bindValue(":PLAYCOMMAND", m_playcommand);
00689         query.bindValue(":CHILDID", m_childID);
00690         query.bindValue(":CATEGORY", m_categoryID);
00691         query.bindValue(":INTID", m_id);
00692     }
00693 
00694     query.bindValue(":TITLE", m_title.isNull() ? "" : m_title);
00695     query.bindValue(":SUBTITLE", m_subtitle.isNull() ? "" : m_subtitle);
00696     query.bindValue(":TAGLINE", m_tagline);
00697     query.bindValue(":DIRECTOR", m_director.isNull() ? "" : m_director);
00698     query.bindValue(":STUDIO", m_studio);
00699     query.bindValue(":PLOT", m_plot);
00700     query.bindValue(":RATING", m_rating.isNull() ? "" : m_rating);
00701     query.bindValue(":YEAR", m_year);
00702     query.bindValue(":RELEASEDATE", m_releasedate);
00703     query.bindValue(":USERRATING", m_userrating);
00704     query.bindValue(":LENGTH", m_length);
00705     query.bindValue(":PLAYCOUNT", m_playcount);
00706     query.bindValue(":SEASON", m_season);
00707     query.bindValue(":EPISODE", m_episode);
00708     query.bindValue(":FILENAME", m_filename);
00709     query.bindValue(":HASH", m_hash);
00710     query.bindValue(":TRAILER", m_trailer.isNull() ? "" : m_trailer);
00711     query.bindValue(":SHOWLEVEL", m_showlevel);
00712     query.bindValue(":COVERFILE", m_coverfile.isNull() ? "" : m_coverfile);
00713     query.bindValue(":SCREENSHOT", m_screenshot.isNull() ? "" : m_screenshot);
00714     query.bindValue(":BANNER", m_banner.isNull() ? "" : m_banner);
00715     query.bindValue(":FANART", m_fanart.isNull() ? "" : m_fanart);
00716     query.bindValue(":INETREF", m_inetref.isNull() ? "" : m_inetref);
00717     query.bindValue(":COLLECTION", m_collectionref);
00718     query.bindValue(":HOMEPAGE", m_homepage.isNull() ? "" : m_homepage);
00719     query.bindValue(":BROWSE", m_browse);
00720     query.bindValue(":WATCHED", m_watched);
00721     query.bindValue(":HOST", m_host);
00722     query.bindValue(":PROCESSED", m_processed);
00723     query.bindValue(":CONTENTTYPE", ContentTypeToString(m_contenttype));
00724 
00725     if (!query.exec() || !query.isActive())
00726     {
00727         MythDB::DBError("video metadata update", query);
00728         return;
00729     }
00730 
00731     if (inserting)
00732     {
00733         // Must make sure we have 'id' filled before we call updateGenres or
00734         // updateCountries
00735 
00736         if (!query.exec("SELECT LAST_INSERT_ID()") || !query.next())
00737         {
00738             MythDB::DBError("metadata id get", query);
00739             return;
00740         }
00741 
00742         m_id = query.value(0).toUInt();
00743 
00744         if (0 == m_id)
00745         {
00746             LOG(VB_GENERAL, LOG_ERR,
00747                 QString("%1: The id of the last inserted row to "
00748                         "videometadata seems to be 0. This is odd.")
00749                     .arg(__FILE__));
00750             return;
00751         }
00752     }
00753 
00754     updateGenres();
00755     updateCountries();
00756     updateCast();
00757 }
00758 
00759 void VideoMetadataImp::SaveToDatabase()
00760 {
00761     saveToDatabase();
00762 }
00763 
00764 void VideoMetadataImp::UpdateDatabase()
00765 {
00766     saveToDatabase();
00767 }
00768 
00769 bool VideoMetadataImp::DeleteFromDatabase()
00770 {
00771     VideoGenreMap::getGenreMap().remove(m_id);
00772     VideoCountryMap::getCountryMap().remove(m_id);
00773     VideoCastMap::getCastMap().remove(m_id);
00774 
00775     MSqlQuery query(MSqlQuery::InitCon());
00776     query.prepare("DELETE FROM videometadata WHERE intid = :ID");
00777     query.bindValue(":ID", m_id);
00778     if (!query.exec())
00779     {
00780         MythDB::DBError("delete from videometadata", query);
00781     }
00782 
00783     query.prepare("DELETE FROM filemarkup WHERE filename = :FILENAME");
00784     query.bindValue(":FILENAME", m_filename);
00785     if (!query.exec())
00786     {
00787         MythDB::DBError("delete from filemarkup", query);
00788     }
00789 
00790     return true;
00791 }
00792 
00793 void VideoMetadataImp::SetCategoryID(int id)
00794 {
00795     if (id == 0)
00796     {
00797         m_category = "";
00798         m_categoryID = id;
00799     }
00800     else
00801     {
00802         if (m_categoryID != id)
00803         {
00804             QString cat;
00805             if (VideoCategory::GetCategory().get(id, cat))
00806             {
00807                 m_category = cat;
00808                 m_categoryID = id;
00809             }
00810             else
00811             {
00812                 LOG(VB_GENERAL, LOG_ERR, "Unknown category id");
00813             }
00814         }
00815     }
00816 }
00817 
00818 void VideoMetadataImp::updateGenres()
00819 {
00820     VideoGenreMap::getGenreMap().remove(m_id);
00821 
00822     // ensure that all genres we have are in the DB
00823     genre_list::iterator genre = m_genres.begin();
00824     while (genre != m_genres.end())
00825     {
00826         if (genre->second.trimmed().length())
00827         {
00828             genre->first = VideoGenre::getGenre().add(genre->second);
00829             VideoGenreMap::getGenreMap().add(m_id, genre->first);
00830             ++genre;
00831         }
00832         else
00833         {
00834             genre = m_genres.erase(genre);
00835         }
00836     }
00837 }
00838 
00839 void VideoMetadataImp::updateCountries()
00840 {
00841     // remove countries for this video
00842     VideoCountryMap::getCountryMap().remove(m_id);
00843 
00844     country_list::iterator country = m_countries.begin();
00845     while (country != m_countries.end())
00846     {
00847         if (country->second.trimmed().length())
00848         {
00849             country->first = VideoCountry::getCountry().add(country->second);
00850             VideoCountryMap::getCountryMap().add(m_id, country->first);
00851             ++country;
00852         }
00853         else
00854         {
00855             country = m_countries.erase(country);
00856         }
00857     }
00858 }
00859 
00860 void VideoMetadataImp::updateCast()
00861 {
00862     VideoCastMap::getCastMap().remove(m_id);
00863 
00864     // ensure that all cast we have are in the DB
00865     cast_list::iterator cast = m_cast.begin();
00866     while (cast != m_cast.end())
00867     {
00868         if (cast->second.trimmed().length())
00869         {
00870             cast->first = VideoCast::GetCast().add(cast->second);
00871             VideoCastMap::getCastMap().add(m_id, cast->first);
00872             ++cast;
00873         }
00874         else
00875         {
00876             cast = m_cast.erase(cast);
00877         }
00878     }
00879 }
00880 
00884 VideoMetadata::SortKey VideoMetadata::GenerateDefaultSortKey(const VideoMetadata &m,
00885                                                    bool ignore_case)
00886 {
00887     QString title(ignore_case ? m.GetTitle().toLower() : m.GetTitle());
00888     title = TrimTitle(title, ignore_case);
00889 
00890     return SortKey(SortData(title, m.GetFilename(),
00891                          QString().sprintf("%.7d", m.GetID())));
00892 }
00893 
00894 namespace
00895 {
00896     QString eatBraces(const QString &title, const QString &left_brace,
00897                       const QString &right_brace)
00898     {
00899         QString ret(title);
00900         bool keep_checking = true;
00901 
00902         while (keep_checking)
00903         {
00904             int left_position = ret.indexOf(left_brace);
00905             int right_position = ret.indexOf(right_brace);
00906             if (left_position == -1 || right_position == -1)
00907             {
00908                 //
00909                 //  No matching sets of these braces left.
00910                 //
00911 
00912                 keep_checking = false;
00913             }
00914             else
00915             {
00916                 if (left_position < right_position)
00917                 {
00918                     //
00919                     //  We have a matching set like:  (  foo  )
00920                     //
00921 
00922                     ret = ret.left(left_position) +
00923                             ret.right(ret.length() - right_position - 1);
00924                 }
00925                 else if (left_position > right_position)
00926                 {
00927                     //
00928                     //  We have a matching set like:  )  foo  (
00929                     //
00930 
00931                     ret = ret.left(right_position) +
00932                             ret.right(ret.length() - left_position - 1);
00933                 }
00934             }
00935         }
00936 
00937         return ret;
00938     }
00939 }
00940 
00941 int VideoMetadata::UpdateHashedDBRecord(const QString &hash,
00942                                    const QString &file_name,
00943                                    const QString &host)
00944 {
00945     MSqlQuery query(MSqlQuery::InitCon());
00946 
00947     query.prepare("SELECT intid,filename FROM videometadata WHERE "
00948                   "hash = :HASH");
00949     query.bindValue(":HASH", hash);
00950 
00951     if (!query.exec() || !query.isActive())
00952     {
00953         MythDB::DBError("Video hashed metadata update", query);
00954         return -1;
00955     }
00956 
00957     if (!query.next())
00958         return -1;
00959 
00960     int intid = query.value(0).toInt();
00961     QString oldfilename = query.value(1).toString();
00962 
00963     query.prepare("UPDATE videometadata SET filename = :FILENAME, "
00964                   "host = :HOST WHERE intid = :INTID");
00965     query.bindValue(":FILENAME", file_name);
00966     query.bindValue(":HOST", host);
00967     query.bindValue(":INTID", intid);
00968 
00969     if (!query.exec() || !query.isActive())
00970     {
00971         MythDB::DBError("Video hashed metadata update (videometadata)", query);
00972         return -1;
00973     }
00974 
00975     query.prepare("UPDATE filemarkup SET filename = :FILENAME "
00976                   "WHERE filename = :OLDFILENAME");
00977     query.bindValue(":FILENAME", file_name);
00978     query.bindValue(":OLDFILENAME", oldfilename);
00979 
00980     if (!query.exec() || !query.isActive())
00981     {
00982         MythDB::DBError("Video hashed metadata update (filemarkup)", query);
00983         return -1;
00984     }
00985 
00986     return intid;
00987 }
00988 
00989 QString VideoMetadata::VideoFileHash(const QString &file_name,
00990                            const QString &host)
00991 {
00992     if (!host.isEmpty() && !gCoreContext->IsMasterHost(host))
00993     {
00994         QString url = generate_file_url("Videos", host, file_name);
00995         return RemoteFile::GetFileHash(url);
00996     }
00997     else if (!host.isEmpty())
00998     {
00999         StorageGroup sgroup("Videos", host);
01000         QString fullname = sgroup.FindFile(file_name);
01001         return FileHash(fullname);
01002     }
01003     else
01004         return FileHash(file_name);
01005 }
01006 
01007 QString VideoMetadata::FilenameToMeta(const QString &file_name, int position)
01008 {
01009     // position 1 returns title, 2 returns season,
01010     //          3 returns episode, 4 returns subtitle
01011 
01012     QString cleanFilename = file_name.left(file_name.lastIndexOf('.'));
01013     cleanFilename.replace(QRegExp("%20"), " ");
01014     cleanFilename.replace(QRegExp("_"), " ");
01015     cleanFilename.replace(QRegExp("\\."), " ");
01016 
01017     QString season_translation = QObject::tr("Season");
01018     QString episode_translation = QObject::tr("Episode");
01019 
01020     // Primary Regexp
01021     QString separator = "(?:\\s?(?:-|/)?\\s?)?";
01022     QString regexp = QString(
01023                   "^(.*[^s0-9])" // Title
01024                   "%1" // optional separator
01025                   "(?:s|(?:%2))?" // season marker
01026                   "%1" // optional separator
01027                   "(\\d{1,4})" // Season
01028                   "%1" // optional separator
01029                   "(?:[ex/]|%3)" // episode marker
01030                   "%1" // optional separator
01031                   "(\\d{1,3})" // Episode
01032                   "%1" // optional separator
01033                   "(.*)$" // Subtitle
01034                   ).arg(separator)
01035                    .arg(season_translation).arg(episode_translation);
01036     QRegExp filename_parse(regexp,
01037                   Qt::CaseInsensitive, QRegExp::RegExp2);
01038 
01039     // Cleanup Regexp
01040     QString regexp2 = QString("(%1(?:%2%1\\d*%1)*%1)$")
01041                              .arg(separator).arg(season_translation);
01042     QRegExp title_parse(regexp2, Qt::CaseInsensitive, QRegExp::RegExp2);
01043 
01044     int pos = filename_parse.indexIn(cleanFilename);
01045     if (pos > -1)
01046     {
01047         QString title = filename_parse.cap(1);
01048         QString season = filename_parse.cap(2);
01049         QString episode = filename_parse.cap(3);
01050         QString subtitle = filename_parse.cap(4);
01051 
01052         // Clean up the title
01053         int pos2 = title_parse.indexIn(title);
01054         if (pos2 > -1)
01055             title = title.left(pos2);
01056         title = title.right(title.length() -
01057                      title.lastIndexOf('/') -1);
01058 
01059         // Return requested value
01060         if (position == 1 && !title.isEmpty())
01061             return title.trimmed();
01062         else if (position == 2)
01063             return season.trimmed();
01064         else if (position == 3)
01065             return episode.trimmed();
01066         else if (position == 4)
01067             return subtitle.trimmed();
01068     }
01069     else if (position == 1)
01070     {
01071         QString title = cleanFilename;
01072 
01073         // Clean up the title
01074         title = title.right(title.length() -
01075                      title.lastIndexOf('/') -1);
01076 
01077         title = eatBraces(title, "[", "]");
01078         title = eatBraces(title, "(", ")");
01079         title = eatBraces(title, "{", "}");
01080         return title.trimmed();
01081     }
01082     else if (position == 2 || position == 3)
01083         return QString("0");
01084 
01085     return QString();
01086 }
01087 
01088 namespace
01089 {
01090     const QRegExp &getTitleTrim(bool ignore_case)
01091     {
01092         static QString pattern(QObject::tr("^(The |A |An )"));
01093         static QRegExp prefixes_case(pattern, Qt::CaseSensitive);
01094         static QRegExp prefixes_nocase(pattern, Qt::CaseInsensitive);
01095         return ignore_case ? prefixes_nocase : prefixes_case;
01096     }
01097 }
01098 
01099 QString VideoMetadata::TrimTitle(const QString &title, bool ignore_case)
01100 {
01101     QString ret(title);
01102     ret.remove(getTitleTrim(ignore_case));
01103     return ret;
01104 }
01105 
01106 VideoMetadata::VideoMetadata(const QString &filename, const QString &hash,
01107              const QString &trailer, const QString &coverfile,
01108              const QString &screenshot, const QString &banner, const QString &fanart,
01109              const QString &title, const QString &subtitle, const QString &tagline,
01110              int year, const QDate &releasedate, const QString &inetref, int collectionref,
01111              const QString &homepage, const QString &director, const QString &studio,
01112              const QString &plot, float userrating, const QString &rating,
01113              int length, int playcount, int season, int episode, const QDate &insertdate,
01114              int id, ParentalLevel::Level showlevel, int categoryID,
01115              int childID, bool browse, bool watched,
01116              const QString &playcommand, const QString &category,
01117              const genre_list &genres,
01118              const country_list &countries,
01119              const cast_list &cast,
01120              const QString &host, bool processed,
01121              VideoContentType contenttype)
01122 {
01123     m_imp = new VideoMetadataImp(filename, hash, trailer, coverfile, screenshot, banner,
01124                             fanart, title, subtitle, tagline, year, releasedate, inetref,
01125                             collectionref, homepage, director, studio, plot, userrating, rating,
01126                             length, playcount, season, episode, insertdate, id, showlevel, categoryID,
01127                             childID, browse, watched, playcommand, category, genres, countries,
01128                             cast, host, processed, contenttype);
01129 }
01130 
01131 VideoMetadata::~VideoMetadata()
01132 {
01133     delete m_imp;
01134 }
01135 
01136 VideoMetadata::VideoMetadata(MSqlQuery &query)
01137 {
01138     m_imp = new VideoMetadataImp(query);
01139 }
01140 
01141 VideoMetadata::VideoMetadata(const VideoMetadata &rhs)
01142 {
01143     *this = rhs;
01144 }
01145 
01146 VideoMetadata &VideoMetadata::operator=(const VideoMetadata &rhs)
01147 {
01148     if (this != &rhs)
01149     {
01150         m_imp = new VideoMetadataImp(*(rhs.m_imp));
01151     }
01152 
01153     return *this;
01154 }
01155 
01156 void VideoMetadata::toMap(MetadataMap &metadataMap)
01157 {
01158     if (this == NULL)
01159         return;
01160 
01161     GetImageMap(metadataMap);
01162 
01163     metadataMap["filename"] = GetFilename();
01164     metadataMap["title"] = GetTitle();
01165     metadataMap["subtitle"] = GetSubtitle();
01166     metadataMap["tagline"] = GetTagline();
01167     metadataMap["director"] = GetDirector();
01168     metadataMap["studio"] = GetStudio();
01169     metadataMap["description"] = GetPlot();
01170     metadataMap["genres"] = GetDisplayGenres(*this);
01171     metadataMap["countries"] = GetDisplayCountries(*this);
01172     metadataMap["cast"] = GetDisplayCast(*this).join(", ");
01173     metadataMap["rating"] = GetDisplayRating(GetRating());
01174     metadataMap["length"] = GetDisplayLength(GetLength());
01175     metadataMap["playcount"] = QString::number(GetPlayCount());
01176     metadataMap["year"] = GetDisplayYear(GetYear());
01177 
01178     metadataMap["releasedate"] = MythDateToString(GetReleaseDate(), kDateFull |
01179                                                                     kAddYear);
01180 
01181     metadataMap["userrating"] = GetDisplayUserRating(GetUserRating());
01182 
01183     if (GetSeason() > 0 || GetEpisode() > 0)
01184     {
01185         metadataMap["season"] = GetDisplaySeasonEpisode(GetSeason(), 1);
01186         metadataMap["episode"] = GetDisplaySeasonEpisode(GetEpisode(), 1);
01187         metadataMap["s##e##"] = QString("s%1e%2").arg(GetDisplaySeasonEpisode
01188                                              (GetSeason(), 2))
01189                         .arg(GetDisplaySeasonEpisode(GetEpisode(), 2));
01190         metadataMap["##x##"] = QString("%1x%2").arg(GetDisplaySeasonEpisode
01191                                              (GetSeason(), 1))
01192                         .arg(GetDisplaySeasonEpisode(GetEpisode(), 2));
01193     }
01194     else
01195     {
01196         metadataMap["s##e##"] = metadataMap["##x##"] = QString();
01197         metadataMap["season"] = metadataMap["episode"] = QString();
01198     }
01199 
01200     GetStateMap(metadataMap);
01201 
01202     metadataMap["insertdate"] = MythDateToString(GetInsertdate(), kDateFull |
01203                                                                   kAddYear);
01204     metadataMap["inetref"] = GetInetRef();
01205     metadataMap["homepage"] = GetHomepage();
01206     metadataMap["child_id"] = QString::number(GetChildID());
01207     metadataMap["browseable"] = GetDisplayBrowse(GetBrowse());
01208     metadataMap["watched"] = GetDisplayWatched(GetWatched());
01209     metadataMap["processed"] = GetDisplayProcessed(GetProcessed());
01210     metadataMap["category"] = GetCategory();
01211 }
01212 
01213 
01214 void VideoMetadata::GetStateMap(MetadataMap& stateMap)
01215 {
01216     stateMap["trailerstate"] = TrailerToState(GetTrailer());
01217     stateMap["userratingstate"] =
01218             QString::number((int)(GetUserRating()));
01219     stateMap["watchedstate"] = WatchedToState(GetWatched());
01220     stateMap["videolevel"] = ParentalLevelToState(GetShowLevel());
01221 }
01222 
01223 void VideoMetadata::GetImageMap(MetadataMap& imageMap)
01224 {
01225     QString coverfile;
01226     if (IsHostSet()
01227         && !GetCoverFile().startsWith("/")
01228         && !GetCoverFile().isEmpty()
01229         && !IsDefaultCoverFile(GetCoverFile()))
01230     {
01231         coverfile = generate_file_url("Coverart", GetHost(),
01232                 GetCoverFile());
01233     }
01234     else
01235     {
01236         coverfile = GetCoverFile();
01237     }
01238 
01239     imageMap["coverfile"] = coverfile;
01240     imageMap["coverart"] = coverfile;
01241 
01242     QString screenshotfile;
01243     if (IsHostSet() && !GetScreenshot().startsWith("/")
01244         && !GetScreenshot().isEmpty())
01245     {
01246         screenshotfile = generate_file_url("Screenshots",
01247                 GetHost(), GetScreenshot());
01248     }
01249     else
01250     {
01251         screenshotfile = GetScreenshot();
01252     }
01253 
01254     imageMap["screenshotfile"] = screenshotfile;
01255     imageMap["screenshot"] = screenshotfile;
01256 
01257     QString bannerfile;
01258     if (IsHostSet() && !GetBanner().startsWith("/")
01259         && !GetBanner().isEmpty())
01260     {
01261         bannerfile = generate_file_url("Banners", GetHost(),
01262                 GetBanner());
01263     }
01264     else
01265     {
01266         bannerfile = GetBanner();
01267     }
01268 
01269     imageMap["bannerfile"] = bannerfile;
01270     imageMap["banner"] = bannerfile;
01271 
01272     QString fanartfile;
01273     if (IsHostSet() && !GetFanart().startsWith("/")
01274         && !GetFanart().isEmpty())
01275     {
01276         fanartfile = generate_file_url("Fanart", GetHost(),
01277                 GetFanart());
01278     }
01279     else
01280     {
01281         fanartfile = GetFanart();
01282     }
01283 
01284     imageMap["fanartfile"] = fanartfile;
01285     imageMap["fanart"] = fanartfile;
01286 
01287     QString smartimage = coverfile;
01288     if (!screenshotfile.isEmpty () && (GetSeason() > 0 || GetEpisode() > 0))
01289         smartimage = screenshotfile;
01290     imageMap["smartimage"] = smartimage;
01291 }
01292 
01293 void ClearMap(MetadataMap &metadataMap)
01294 {
01295     metadataMap["coverfile"] = "";
01296     metadataMap["screenshotfile"] = "";
01297     metadataMap["bannerfile"] = "";
01298     metadataMap["fanartfile"] = "";
01299     metadataMap["filename"] = "";
01300     metadataMap["title"] = "";
01301     metadataMap["subtitle"] = "";
01302     metadataMap["tagline"] = "";
01303     metadataMap["director"] = "";
01304     metadataMap["studio"] = "";
01305     metadataMap["description"] = "";
01306     metadataMap["genres"] = "";
01307     metadataMap["countries"] = "";
01308     metadataMap["cast"] = "";
01309     metadataMap["rating"] = "";
01310     metadataMap["length"] = "";
01311     metadataMap["playcount"] = "";
01312     metadataMap["year"] = "";
01313     metadataMap["releasedate"] = "";
01314     metadataMap["userrating"] = "";
01315     metadataMap["season"] = "";
01316     metadataMap["episode"] = "";
01317     metadataMap["s##e##"] = "";
01318     metadataMap["##x##"] = "";
01319     metadataMap["trailerstate"] = "";
01320     metadataMap["userratingstate"] = "";
01321     metadataMap["watchedstate"] = "";
01322     metadataMap["videolevel"] = "";
01323     metadataMap["insertdate"] = "";
01324     metadataMap["inetref"] = "";
01325     metadataMap["homepage"] = "";
01326     metadataMap["child_id"] = "";
01327     metadataMap["browseable"] = "";
01328     metadataMap["watched"] = "";
01329     metadataMap["category"] = "";
01330     metadataMap["processed"] = "";
01331 }
01332 
01333 bool VideoMetadata::HasSortKey() const
01334 {
01335     return m_imp->HasSortKey();
01336 }
01337 
01338 const VideoMetadata::SortKey &VideoMetadata::GetSortKey() const
01339 {
01340     return m_imp->GetSortKey();
01341 }
01342 
01343 void VideoMetadata::SetSortKey(const VideoMetadata::SortKey &sort_key)
01344 {
01345     m_imp->SetSortKey(sort_key);
01346 }
01347 
01348 const QString &VideoMetadata::GetPrefix() const
01349 {
01350     return m_imp->GetPrefix();
01351 }
01352 
01353 void VideoMetadata::SetPrefix(const QString &prefix)
01354 {
01355     m_imp->SetPrefix(prefix);
01356 }
01357 
01358 const QString &VideoMetadata::GetTitle() const
01359 {
01360     return m_imp->getTitle();
01361 }
01362 
01363 void VideoMetadata::SetTitle(const QString &title)
01364 {
01365     m_imp->SetTitle(title);
01366 }
01367 
01368 const QString &VideoMetadata::GetSubtitle() const
01369 {
01370     return m_imp->getSubtitle();
01371 }
01372 
01373 void VideoMetadata::SetSubtitle(const QString &subtitle)
01374 {
01375     m_imp->SetSubtitle(subtitle);
01376 }
01377 
01378 const QString &VideoMetadata::GetTagline() const
01379 {
01380     return m_imp->GetTagline();
01381 }
01382 
01383 void VideoMetadata::SetTagline(const QString &tagline)
01384 {
01385     m_imp->SetTagline(tagline);
01386 }
01387 
01388 int VideoMetadata::GetYear() const
01389 {
01390     return m_imp->getYear();
01391 }
01392 
01393 void VideoMetadata::SetYear(int year)
01394 {
01395     m_imp->SetYear(year);
01396 }
01397 
01398 QDate VideoMetadata::GetReleaseDate() const
01399 {
01400     return m_imp->getReleaseDate();
01401 }
01402 
01403 void VideoMetadata::SetReleaseDate(QDate releasedate)
01404 {
01405     m_imp->SetReleaseDate(releasedate);
01406 }
01407 
01408 const QString &VideoMetadata::GetInetRef() const
01409 {
01410     return m_imp->GetInetRef();
01411 }
01412 
01413 void VideoMetadata::SetInetRef(const QString &inetRef)
01414 {
01415     m_imp->SetInetRef(inetRef);
01416 }
01417 
01418 int VideoMetadata::GetCollectionRef() const
01419 {
01420     return m_imp->GetCollectionRef();
01421 }
01422 
01423 void VideoMetadata::SetCollectionRef(int collectionref)
01424 {
01425     m_imp->SetCollectionRef(collectionref);
01426 }
01427 
01428 const QString &VideoMetadata::GetHomepage() const
01429 {
01430     return m_imp->GetHomepage();
01431 }
01432 
01433 void VideoMetadata::SetHomepage(const QString &homepage)
01434 {
01435     m_imp->SetHomepage(homepage);
01436 }
01437 
01438 const QString &VideoMetadata::GetDirector() const
01439 {
01440     return m_imp->getDirector();
01441 }
01442 
01443 void VideoMetadata::SetDirector(const QString &director)
01444 {
01445     m_imp->SetDirector(director);
01446 }
01447 
01448 const QString &VideoMetadata::GetStudio() const
01449 {
01450     return m_imp->getStudio();
01451 }
01452 
01453 void VideoMetadata::SetStudio(const QString &studio)
01454 {
01455     m_imp->SetStudio(studio);
01456 }
01457 
01458 const QString &VideoMetadata::GetPlot() const
01459 {
01460     return m_imp->getPlot();
01461 }
01462 
01463 void VideoMetadata::SetPlot(const QString &plot)
01464 {
01465     m_imp->SetPlot(plot);
01466 }
01467 
01468 float VideoMetadata::GetUserRating() const
01469 {
01470     return m_imp->GetUserRating();
01471 }
01472 
01473 void VideoMetadata::SetUserRating(float userRating)
01474 {
01475     m_imp->SetUserRating(userRating);
01476 }
01477 
01478 const QString &VideoMetadata::GetRating() const
01479 {
01480     return m_imp->GetRating();
01481 }
01482 
01483 void VideoMetadata::SetRating(const QString &rating)
01484 {
01485     m_imp->SetRating(rating);
01486 }
01487 
01488 int VideoMetadata::GetLength() const
01489 {
01490     return m_imp->GetLength();
01491 }
01492 
01493 void VideoMetadata::SetLength(int length)
01494 {
01495     m_imp->SetLength(length);
01496 }
01497 
01498 unsigned int VideoMetadata::GetPlayCount() const
01499 {
01500     return m_imp->GetPlayCount();
01501 }
01502 
01503 void VideoMetadata::SetPlayCount(int count)
01504 {
01505     m_imp->SetPlayCount(count);
01506 }
01507 
01508 int VideoMetadata::GetSeason() const
01509 {
01510     return m_imp->GetSeason();
01511 }
01512 
01513 void VideoMetadata::SetSeason(int season)
01514 {
01515     m_imp->SetSeason(season);
01516 }
01517 
01518 int VideoMetadata::GetEpisode() const
01519 {
01520     return m_imp->GetEpisode();
01521 }
01522 
01523 void VideoMetadata::SetEpisode(int episode)
01524 {
01525     m_imp->SetEpisode(episode);
01526 }
01527 
01528 QDate VideoMetadata::GetInsertdate() const
01529 {
01530     return m_imp->GetInsertdate();
01531 }
01532 
01533 void VideoMetadata::SetInsertdate(QDate date)
01534 {
01535     m_imp->SetInsertdate(date);
01536 }
01537 
01538 unsigned int VideoMetadata::GetID() const
01539 {
01540     return m_imp->GetID();
01541 }
01542 
01543 void VideoMetadata::SetID(int id)
01544 {
01545     m_imp->SetID(id);
01546 }
01547 
01548 int VideoMetadata::GetChildID() const
01549 {
01550     return m_imp->GetChildID();
01551 }
01552 
01553 void VideoMetadata::SetChildID(int childID)
01554 {
01555     m_imp->SetChildID(childID);
01556 }
01557 
01558 bool VideoMetadata::GetBrowse() const
01559 {
01560     return m_imp->GetBrowse();
01561 }
01562 
01563 void VideoMetadata::SetBrowse(bool browse)
01564 {
01565     m_imp->SetBrowse(browse);
01566 }
01567 
01568 bool VideoMetadata::GetWatched() const
01569 {
01570     return m_imp->GetWatched();
01571 }
01572 
01573 void VideoMetadata::SetWatched(bool watched)
01574 {
01575     m_imp->SetWatched(watched);
01576 }
01577 
01578 bool VideoMetadata::GetProcessed() const
01579 {
01580     return m_imp->GetProcessed();
01581 }
01582 
01583 void VideoMetadata::SetProcessed(bool processed)
01584 {
01585     m_imp->SetProcessed(processed);
01586 }
01587 
01588 VideoContentType VideoMetadata::GetContentType() const
01589 {
01590     return m_imp->GetContentType();
01591 }
01592 
01593 void VideoMetadata::SetContentType(VideoContentType contenttype)
01594 {
01595     m_imp->SetContentType(contenttype);
01596 }
01597 
01598 const QString &VideoMetadata::GetPlayCommand() const
01599 {
01600     return m_imp->getPlayCommand();
01601 }
01602 
01603 void VideoMetadata::SetPlayCommand(const QString &playCommand)
01604 {
01605     m_imp->SetPlayCommand(playCommand);
01606 }
01607 
01608 ParentalLevel::Level VideoMetadata::GetShowLevel() const
01609 {
01610     return m_imp->GetShowLevel();
01611 }
01612 
01613 void VideoMetadata::SetShowLevel(ParentalLevel::Level showLevel)
01614 {
01615     m_imp->SetShowLevel(showLevel);
01616 }
01617 
01618 const QString &VideoMetadata::GetFilename() const
01619 {
01620     return m_imp->getFilename();
01621 }
01622 
01623 const QString &VideoMetadata::GetHash() const
01624 {
01625     return m_imp->GetHash();
01626 }
01627 
01628 void VideoMetadata::SetHash(const QString &hash)
01629 {
01630     return m_imp->SetHash(hash);
01631 }
01632 
01633 const QString &VideoMetadata::GetHost() const
01634 {
01635     return m_imp->GetHost();
01636 }
01637 
01638 void VideoMetadata::SetHost(const QString &host)
01639 {
01640         m_imp->SetHost(host);
01641 }
01642 
01643 void VideoMetadata::SetFilename(const QString &filename)
01644 {
01645     m_imp->SetFilename(filename);
01646 }
01647 
01648 const QString &VideoMetadata::GetTrailer() const
01649 {
01650     return m_imp->GetTrailer();
01651 }
01652 
01653 void VideoMetadata::SetTrailer(const QString &trailer)
01654 {
01655     m_imp->SetTrailer(trailer);
01656 }
01657 
01658 const QString &VideoMetadata::GetCoverFile() const
01659 {
01660     return m_imp->GetCoverFile();
01661 }
01662 
01663 void VideoMetadata::SetCoverFile(const QString &coverFile)
01664 {
01665     m_imp->SetCoverFile(coverFile);
01666 }
01667 
01668 const QString &VideoMetadata::GetScreenshot() const
01669 {
01670     return m_imp->GetScreenshot();
01671 }
01672 
01673 void VideoMetadata::SetScreenshot(const QString &screenshot)
01674 {
01675     m_imp->SetScreenshot(screenshot);
01676 }
01677 
01678 const QString &VideoMetadata::GetBanner() const
01679 {
01680     return m_imp->GetBanner();
01681 }
01682 
01683 void VideoMetadata::SetBanner(const QString &banner)
01684 {
01685     m_imp->SetBanner(banner);
01686 }
01687 
01688 const QString &VideoMetadata::GetFanart() const
01689 {
01690     return m_imp->GetFanart();
01691 }
01692 
01693 void VideoMetadata::SetFanart(const QString &fanart)
01694 {
01695     m_imp->SetFanart(fanart);
01696 }
01697 
01698 const QString &VideoMetadata::GetCategory() const
01699 {
01700     return m_imp->GetCategory();
01701 }
01702 
01703 //void VideoMetadata::SetCategory(const QString &category)
01704 //{
01705 //    m_imp->SetCategory(category);
01706 //}
01707 
01708 const VideoMetadata::genre_list &VideoMetadata::GetGenres() const
01709 {
01710     return m_imp->getGenres();
01711 }
01712 
01713 void VideoMetadata::SetGenres(const genre_list &genres)
01714 {
01715     m_imp->SetGenres(genres);
01716 }
01717 
01718 const VideoMetadata::cast_list &VideoMetadata::GetCast() const
01719 {
01720     return m_imp->GetCast();
01721 }
01722 
01723 void VideoMetadata::SetCast(const cast_list &cast)
01724 {
01725     m_imp->SetCast(cast);
01726 }
01727 
01728 const VideoMetadata::country_list &VideoMetadata::GetCountries() const
01729 {
01730     return m_imp->GetCountries();
01731 }
01732 
01733 void VideoMetadata::SetCountries(const country_list &countries)
01734 {
01735     m_imp->SetCountries(countries);
01736 }
01737 
01738 int VideoMetadata::GetCategoryID() const
01739 {
01740     return m_imp->GetCategoryID();
01741 }
01742 
01743 void VideoMetadata::SetCategoryID(int id)
01744 {
01745     m_imp->SetCategoryID(id);
01746 }
01747 
01748 void VideoMetadata::SaveToDatabase()
01749 {
01750     m_imp->SaveToDatabase();
01751 }
01752 
01753 void VideoMetadata::UpdateDatabase()
01754 {
01755     m_imp->UpdateDatabase();
01756 }
01757 
01758 bool VideoMetadata::DeleteFromDatabase()
01759 {
01760     return m_imp->DeleteFromDatabase();
01761 }
01762 
01763 #if 0
01764 bool VideoMetadata::fillDataFromID(const VideoMetadataListManager &cache)
01765 {
01766     if (m_imp->getID() == 0)
01767         return false;
01768 
01769     VideoMetadataListManager::VideoMetadataPtr mp = cache.byID(m_imp->getID());
01770     if (mp.get())
01771     {
01772         *this = *mp;
01773         return true;
01774     }
01775 
01776     return false;
01777 }
01778 #endif
01779 
01780 bool VideoMetadata::FillDataFromFilename(const VideoMetadataListManager &cache)
01781 {
01782     if (m_imp->getFilename().isEmpty())
01783         return false;
01784 
01785     VideoMetadataListManager::VideoMetadataPtr mp =
01786             cache.byFilename(m_imp->getFilename());
01787     if (mp)
01788     {
01789         *this = *mp;
01790         return true;
01791     }
01792 
01793     return false;
01794 }
01795 
01796 bool VideoMetadata::DeleteFile()
01797 {
01798     return m_imp->DeleteFile();
01799 }
01800 
01801 void VideoMetadata::Reset()
01802 {
01803     m_imp->Reset();
01804 }
01805 
01806 bool VideoMetadata::IsHostSet() const
01807 {
01808     return m_imp->IsHostSet();
01809 }
01810 
01811 bool operator==(const VideoMetadata& a, const VideoMetadata& b)
01812 {
01813     if (a.GetFilename() == b.GetFilename())
01814         return true;
01815     return false;
01816 }
01817 
01818 bool operator!=(const VideoMetadata& a, const VideoMetadata& b)
01819 {
01820     if (a.GetFilename() != b.GetFilename())
01821         return true;
01822     return false;
01823 }
01824 
01825 bool operator<(const VideoMetadata::SortKey &lhs, const VideoMetadata::SortKey &rhs)
01826 {
01827     if (lhs.m_sd && rhs.m_sd)
01828         return *lhs.m_sd < *rhs.m_sd;
01829     else
01830     {
01831         LOG(VB_GENERAL, LOG_ERR,
01832             "Error: Bug, Metadata item with empty sort key compared");
01833         return lhs.m_sd < rhs.m_sd;
01834     }
01835 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends