From 8911af523e83f34b945bf15e5304758f1c8afc67 Mon Sep 17 00:00:00 2001 From: Robert McNamara Date: Tue, 12 Jul 2011 00:15:51 -0700 Subject: [PATCH] PlaybackBox: Remove Image Hunt in favor of user-selected artwork. (and incur the ire of those who think the image hunt is "good enough") http://www.mythtv.org/wiki/Enhancing_Recordings_with_Metadata_Lookup#Picking_Artwork_for_Your_Recording_Rules As documented above, remove the costly, slow image hunt and instead allow the user to assign exactly the images they want, to exactly which recording rules, and even to particular seasons within that rule. I will work on ways to pre-populate recording rules in the coming days. Possibly a one-time set of image hunts in mythmetadatalookup that fills the recordedartwork table. --- mythtv/programs/mythfrontend/playbackbox.cpp | 68 +++---- .../mythfrontend/playbackboxhelper.cpp | 186 +++--------------- .../programs/mythfrontend/playbackboxhelper.h | 19 +- 3 files changed, 59 insertions(+), 214 deletions(-) diff --git a/mythtv/programs/mythfrontend/playbackbox.cpp b/mythtv/programs/mythfrontend/playbackbox.cpp index 5ef753aea2b..4991007e1db 100644 --- a/mythtv/programs/mythfrontend/playbackbox.cpp +++ b/mythtv/programs/mythfrontend/playbackbox.cpp @@ -164,8 +164,6 @@ static bool comp_recordDate_rev_less_than( return comp_recordDate_rev(a, b) < 0; } -static const ArtworkType s_artType[] = - { kArtworkFan, kArtworkBanner, kArtworkCover, }; static const uint s_artDelay[] = { kArtworkFanTimeout, kArtworkBannerTimeout, kArtworkCoverTimeout,}; @@ -489,9 +487,9 @@ bool PlaybackBox::Create() m_noRecordingsText = dynamic_cast (GetChild("norecordings")); m_previewImage = dynamic_cast(GetChild("preview")); - m_artImage[kArtworkFan] = dynamic_cast(GetChild("fanart")); - m_artImage[kArtworkBanner] = dynamic_cast(GetChild("banner")); - m_artImage[kArtworkCover]= dynamic_cast(GetChild("coverart")); + m_artImage[FANART] = dynamic_cast(GetChild("fanart")); + m_artImage[BANNER] = dynamic_cast(GetChild("banner")); + m_artImage[COVERART]= dynamic_cast(GetChild("coverart")); if (!m_recordingList || !m_groupList) { @@ -515,9 +513,9 @@ bool PlaybackBox::Create() SLOT(ItemVisible(MythUIButtonListItem*))); // connect up timers... - connect(m_artTimer[kArtworkFan], SIGNAL(timeout()), SLOT(fanartLoad())); - connect(m_artTimer[kArtworkBanner],SIGNAL(timeout()), SLOT(bannerLoad())); - connect(m_artTimer[kArtworkCover], SIGNAL(timeout()), SLOT(coverartLoad())); + connect(m_artTimer[FANART], SIGNAL(timeout()), SLOT(fanartLoad())); + connect(m_artTimer[BANNER], SIGNAL(timeout()), SLOT(bannerLoad())); + connect(m_artTimer[COVERART], SIGNAL(timeout()), SLOT(coverartLoad())); BuildFocusList(); m_programInfoCache.ScheduleLoad(false); @@ -622,32 +620,29 @@ void PlaybackBox::updateGroupInfo(const QString &groupname, infoMap["show"] = grouplabel; } - if (m_artImage[kArtworkFan]) + if (m_artImage[FANART]) { if (!groupname.isEmpty() && !m_progLists[groupname].empty()) { ProgramInfo *pginfo = *m_progLists[groupname].begin(); - QString arthost((!m_artHostOverride.isEmpty()) ? - m_artHostOverride : pginfo->GetHostname()); - QString artworkSeriesID = "_GROUP_"; QString fn = m_helper.LocateArtwork( - artworkSeriesID, groupname, kArtworkFan, arthost, NULL); + pginfo->GetInetRef(), pginfo->GetSeason(), FANART, NULL, groupname); if (fn.isEmpty()) { - m_artTimer[kArtworkFan]->stop(); - m_artImage[kArtworkFan]->Reset(); + m_artTimer[FANART]->stop(); + m_artImage[FANART]->Reset(); } - else if (m_artImage[kArtworkFan]->GetFilename() != fn) + else if (m_artImage[FANART]->GetFilename() != fn) { - m_artImage[kArtworkFan]->SetFilename(fn); - m_artTimer[kArtworkFan]->start(kArtworkFanTimeout); + m_artImage[FANART]->SetFilename(fn); + m_artTimer[FANART]->start(kArtworkFanTimeout); } } else { - m_artImage[kArtworkFan]->Reset(); + m_artImage[FANART]->Reset(); } } @@ -696,11 +691,11 @@ void PlaybackBox::updateGroupInfo(const QString &groupname, if (m_previewImage) m_previewImage->Reset(); - if (m_artImage[kArtworkBanner]) - m_artImage[kArtworkBanner]->Reset(); + if (m_artImage[BANNER]) + m_artImage[BANNER]->Reset(); - if (m_artImage[kArtworkCover]) - m_artImage[kArtworkCover]->Reset(); + if (m_artImage[COVERART]) + m_artImage[COVERART]->Reset(); updateIcons(); } @@ -847,8 +842,8 @@ void PlaybackBox::UpdateUIListItem( } QString fn = m_helper.LocateArtwork( - pginfo->GetSeriesID(), pginfo->GetTitle(), - s_artType[i], arthost, pginfo); + pginfo->GetInetRef(), pginfo->GetSeason(), + (VideoArtworkType)i, pginfo); if (fn.isEmpty()) { @@ -2442,17 +2437,17 @@ void PlaybackBox::RemoveProgram( void PlaybackBox::fanartLoad(void) { - m_artImage[kArtworkFan]->Load(); + m_artImage[FANART]->Load(); } void PlaybackBox::bannerLoad(void) { - m_artImage[kArtworkBanner]->Load(); + m_artImage[BANNER]->Load(); } void PlaybackBox::coverartLoad(void) { - m_artImage[kArtworkCover]->Load(); + m_artImage[COVERART]->Load(); } void PlaybackBox::ShowDeletePopup(DeletePopupType type) @@ -4116,15 +4111,14 @@ void PlaybackBox::customEvent(QEvent *event) if (info) info->SetPathname(me->ExtraData(1)); } - else if ((message == "FOUND_ARTWORK") && (me->ExtraDataCount() >= 6)) + else if ((message == "FOUND_ARTWORK") && (me->ExtraDataCount() >= 5)) { - QString seriesid = me->ExtraData(0); - QString groupname = me->ExtraData(1); - ArtworkType type = (ArtworkType) me->ExtraData(2).toInt(); - QString pikey = me->ExtraData(4); - QString fn = me->ExtraData(5); + VideoArtworkType type = (VideoArtworkType) me->ExtraData(2).toInt(); + QString pikey = me->ExtraData(3); + QString group = me->ExtraData(4); + QString fn = me->ExtraData(5); - if (seriesid != "_GROUP_" && !pikey.isEmpty()) + if (!pikey.isEmpty()) { ProgramInfo *pginfo = m_programInfoCache.GetProgramInfo(pikey); if (pginfo && @@ -4136,8 +4130,8 @@ void PlaybackBox::customEvent(QEvent *event) m_artTimer[(uint)type]->start(s_artDelay[(uint)type]); } } - else if (seriesid == "_GROUP_" && !groupname.isEmpty() && - (m_currentGroup == groupname) && + else if (!group.isEmpty() && + (m_currentGroup == group) && m_artImage[type] && m_groupList->GetItemCurrent() && m_artImage[(uint)type]->GetFilename() != fn) diff --git a/mythtv/programs/mythfrontend/playbackboxhelper.cpp b/mythtv/programs/mythfrontend/playbackboxhelper.cpp index 2d160562545..46e9955620b 100644 --- a/mythtv/programs/mythfrontend/playbackboxhelper.cpp +++ b/mythtv/programs/mythfrontend/playbackboxhelper.cpp @@ -8,6 +8,7 @@ using namespace std; #include #include "previewgeneratorqueue.h" +#include "metadataimagehelper.h" #include "playbackboxhelper.h" #include "mythcorecontext.h" #include "tvremoteutil.h" @@ -22,52 +23,6 @@ using namespace std; #define LOC_WARN QString("PlaybackBoxHelper Warning: ") #define LOC_ERR QString("PlaybackBoxHelper Error: ") -QString toString(ArtworkType t) -{ - switch (t) - { - case kArtworkFan: return "fanart"; - case kArtworkBanner: return "banner"; - case kArtworkCover: return "coverart"; - } - return QString(); -} - -QString toLocalDir(ArtworkType t) -{ - static QMutex m; - static bool initrun = false; - static QString kFanDir, kBannerDir, kCoverDir; - - QMutexLocker locker(&m); - if (!initrun) - { - kFanDir = gCoreContext->GetSetting("mythvideo.fanartDir"); - kBannerDir = gCoreContext->GetSetting("mythvideo.bannerDir"); - kCoverDir = gCoreContext->GetSetting("VideoArtworkDir"); - initrun = true; - } - - switch (t) - { - case kArtworkFan: return kFanDir; - case kArtworkBanner: return kBannerDir; - case kArtworkCover: return kCoverDir; - } - return QString(); -} - -QString toSG(ArtworkType t) -{ - switch (t) - { - case kArtworkFan: return "Fanart"; - case kArtworkBanner: return "Banners"; - case kArtworkCover: return "Coverart"; - } - return QString(); -} - class PBHEventHandler : public QObject { public: @@ -311,121 +266,23 @@ bool PBHEventHandler::event(QEvent *e) } else if (me->Message() == "LOCATE_ARTWORK") { - QString seriesid = me->ExtraData(0); - QString title = me->ExtraData(1); - const ArtworkType type = (ArtworkType)me->ExtraData(2).toInt(); - const QString host = me->ExtraData(3); - const QString sgroup = toSG(type); - const QString localDir = toLocalDir(type); - const QString cacheKey = QString("%1:%2:%3") - .arg((int)type).arg(seriesid).arg(title); - - seriesid = (seriesid == "_GROUP_") ? QString() : seriesid; - - // Attempts to match image file in specified directory. - // Falls back like this: - // - // Pushing Daisies 5.png - // PushingDaisies5.png - // PushingDaisiesSeason5.png - // Pushing Daisies Season 5 Episode 1.png - // PuShinG DaisIES s05e01.png - // etc. (you get it) - // - // Or any permutation thereof including -,_, or . instead of space - // Then, match by seriesid (for future PBB grabber): - // - // EP0012345.png - // - // Then, as a final fallback, match just title - // - // Pushing Daisies.png (or Pushing_Daisies.png, etc.) - // - // All this allows for grabber to grab an image with format: - // - // Title SeasonNumber.ext or Title SeasonNum # Epnum #.ext - // or SeriesID.ext or Title.ext (without caring about cases, - // spaces, dashes, periods, or underscores) - - QDir dir(localDir); - dir.setSorting(QDir::Name | QDir::Reversed | QDir::IgnoreCase); - - QStringList entries = dir.entryList(); - QString grpHost = sgroup + ":" + host; - - if (!m_fileListCache.contains(grpHost)) - { - QStringList sgEntries; - RemoteGetFileList(host, "", &sgEntries, sgroup, true); - m_fileListCache[grpHost] = sgEntries; - } - - title.replace(' ', "(?:\\s|-|_|\\.)?"); - QString regs[] = { - QString("%1" // title - "(?:\\s|-|_|\\.)?" // optional separator - "(?:" // begin optional Season portion - "S(?:eason)?" // optional "S" or "Season" - "(?:\\s|-|_|\\.)?" // optional separator - "[0-9]{1,3}" // number - ")?" // end optional Season portion - "(?:" // begin optional Episode portion - "(?:\\s|-|_|\\.)?" // optional separator - "(?:x?" // optional "x" - "(?:\\s|-|_|\\.)?" // optional separator - "(?:E(?:pisode)?)?" // optional "E" or "Episode" - "(?:\\s|-|_|\\.)?)?" // optional separator - "[0-9]{1,3}" // number portion of - // optional Episode portion - ")?" // end optional Episode portion - "(?:_%2)?" // optional Suffix portion - "\\.(?:png|gif|jpg)" // file extension - ).arg(title).arg(toString(type)), - QString("%1_%2\\.(?:png|jpg|gif)") - .arg(seriesid).arg(toString(type)), - QString("%1\\.(?:png|jpg|gif)").arg(seriesid), - }; - - QString foundFile; - for (uint i = 0; i < sizeof(regs) / sizeof(QString); i++) - { - QRegExp re(regs[i], Qt::CaseInsensitive); + QString inetref = me->ExtraData(0); + uint season = me->ExtraData(1).toUInt(); + const VideoArtworkType type = (VideoArtworkType)me->ExtraData(2).toInt(); + const QString pikey = me->ExtraData(3); + const QString group = me->ExtraData(4); + const QString cacheKey = QString("%1:%2:%3") + .arg((int)type).arg(inetref).arg(season); - for (QStringList::const_iterator it = entries.begin(); - it != entries.end(); ++it) - { - if (re.exactMatch(*it)) - { - foundFile = *it; - break; - } - } + ArtworkMap map = GetArtwork(inetref, season); - for (QStringList::const_iterator it = - m_fileListCache[grpHost].begin(); - it != m_fileListCache[grpHost].end(); ++it) - { - if (!re.exactMatch(*it)) - continue; - foundFile = gCoreContext->GenMythURL( - gCoreContext->GetSettingOnHost("BackendServerIP", host), - gCoreContext->GetSettingOnHost("BackendServerPort", host).toInt(), - *it, - StorageGroup::GetGroupToUse(host, sgroup)); - - break; - } - } + ArtworkInfo info = map.value(type); - if (!foundFile.isEmpty()) - { - if (localDir.endsWith("/")) - localDir.left(localDir.length()-1); - if (!foundFile.startsWith("myth://")) - foundFile = QString("%1/%2").arg(localDir).arg(foundFile); - } + QString foundFile; + if (!info.url.isEmpty()) { + foundFile = info.url; QMutexLocker locker(&m_pbh.m_lock); m_pbh.m_artworkFilenameCache[cacheKey] = foundFile; } @@ -577,12 +434,13 @@ void PlaybackBoxHelper::CheckAvailability( } QString PlaybackBoxHelper::LocateArtwork( - const QString &seriesid, const QString &title, - ArtworkType type, const QString &host, - const ProgramInfo *pginfo) + const QString &inetref, uint season, + const VideoArtworkType type, + const ProgramInfo *pginfo, + const QString &groupname) { QString cacheKey = QString("%1:%2:%3") - .arg((int)type).arg(seriesid).arg(title); + .arg((int)type).arg(inetref).arg(season); QMutexLocker locker(&m_lock); @@ -592,11 +450,11 @@ QString PlaybackBoxHelper::LocateArtwork( if (it != m_artworkFilenameCache.end()) return *it; - QStringList list(seriesid); - list.push_back(title); - list.push_back(QString::number((int)type)); - list.push_back(host); + QStringList list(inetref); + list.push_back(QString::number(season)); + list.push_back(QString::number(type)); list.push_back((pginfo)?pginfo->MakeUniqueKey():""); + list.push_back(groupname); MythEvent *e = new MythEvent("LOCATE_ARTWORK", list); QCoreApplication::postEvent(m_eventHandler, e); diff --git a/mythtv/programs/mythfrontend/playbackboxhelper.h b/mythtv/programs/mythfrontend/playbackboxhelper.h index c91fc357054..ba9e0c73d48 100644 --- a/mythtv/programs/mythfrontend/playbackboxhelper.h +++ b/mythtv/programs/mythfrontend/playbackboxhelper.h @@ -10,6 +10,9 @@ #include #include +#include "mythcorecontext.h" +#include "metadatacommon.h" + class PreviewGenerator; class PBHEventHandler; class ProgramInfo; @@ -24,16 +27,6 @@ typedef enum CheckAvailabilityType { kCheckForPlaylistAction, } CheckAvailabilityType; -typedef enum ArtworkTypes -{ - kArtworkFan = 0, - kArtworkBanner = 1, - kArtworkCover = 2, -} ArtworkType; -QString toString(ArtworkType t); -QString toLocalDir(ArtworkType t); -QString toSG(ArtworkType t); - class PlaybackBoxHelper : public QThread { friend class PBHEventHandler; @@ -55,9 +48,9 @@ class PlaybackBoxHelper : public QThread CheckAvailabilityType cat = kCheckForCache); QString GetPreviewImage(const ProgramInfo&, bool check_availibility = true); - QString LocateArtwork(const QString &seriesid, const QString &title, - ArtworkType, const QString &host, - const ProgramInfo *pginfo); + QString LocateArtwork(const QString &inetref, uint season, + VideoArtworkType type, const ProgramInfo *pginfo, + const QString &groupname = NULL); virtual void run(void); // QThread