Ticket #13159: mythtv-13159-PreferExactTitleMatchesForMetadata2.patch

File mythtv-13159-PreferExactTitleMatchesForMetadata2.patch, 11.9 KB (added by Steve Erlenborn, 6 years ago)

Updated patch to handle some tricky lookup scenarios

  • mythtv/libs/libmythmetadata/metadatacommon.cpp

    diff --git a/mythtv/libs/libmythmetadata/metadatacommon.cpp b/mythtv/libs/libmythmetadata/metadatacommon.cpp
    index d28d54e..14f1a9e 100644
    a b MetadataLookup::MetadataLookup( 
    219219    m_artwork(artwork),
    220220    m_downloads(downloads)
    221221{
     222    QString manRecSuffix = QString(" (%1)").arg(QObject::tr("Manual Record"));
     223    m_base_title = title;
     224    m_base_title.replace(manRecSuffix,"");
    222225}
    223226
    224227// ProgramInfo-style constructor
    MetadataLookup::MetadataLookup( 
    312315    m_popularity = 0;
    313316    m_budget = 0;
    314317    m_revenue = 0;
     318    QString manRecSuffix = QString(" (%1)").arg(QObject::tr("Manual Record"));
     319    m_base_title = title;
     320    m_base_title.replace(manRecSuffix,"");
    315321}
    316322
    317323// XBMC NFO-style constructor
    MetadataLookup::MetadataLookup( 
    388394    m_artwork(artwork),
    389395    m_downloads(downloads)
    390396{
     397    QString manRecSuffix = QString(" (%1)").arg(QObject::tr("Manual Record"));
     398    m_base_title = title;
     399    m_base_title.replace(manRecSuffix,"");
    391400}
    392401
    393402MetadataLookup::~MetadataLookup()
  • mythtv/libs/libmythmetadata/metadatadownload.cpp

    diff --git a/mythtv/libs/libmythmetadata/metadatadownload.cpp b/mythtv/libs/libmythmetadata/metadatadownload.cpp
    index bf5d4fb..b0f1687 100644
    a b void MetadataDownload::run() 
    9797            lookup->GetType() == kMetadataRecording)
    9898        {
    9999            if (lookup->GetSubtype() == kProbableTelevision)
     100            {
    100101                list = handleTelevision(lookup);
     102                if (findExactMatchWithArtCount(list, lookup->GetBaseTitle()) == 0)
     103                {
     104                    // There are no exact match prospects with artwork from TV search,
     105                    // so add in movies, where we might find a better match.
     106                    list.append(handleMovie(lookup));
     107                }
     108            }
    101109            else if (lookup->GetSubtype() == kProbableMovie)
     110            {
    102111                list = handleMovie(lookup);
     112                if (findExactMatchWithArtCount(list, lookup->GetBaseTitle()) == 0)
     113                {
     114                    // There are no exact match prospects with artwork from Movie search
     115                    // so add in television, where we might find a better match.
     116                    list.append(handleTelevision(lookup));
     117                }
     118            }
    103119            else
    104120            {
    105121                // will try both movie and TV
    void MetadataDownload::run() 
    199215    RunEpilog();
    200216}
    201217
     218unsigned int MetadataDownload::findExactMatchWithArtCount(MetadataLookupList list,
     219                                                          const QString &originaltitle) const
     220{
     221    unsigned int exactMatchesWithArt = 0;
     222
     223    for (MetadataLookupList::const_iterator i = list.begin();
     224            i != list.end(); ++i)
     225    {
     226        QString title = (*i)->GetTitle();
     227        // Consider exact title matches (ignoring case)
     228        if ((QString::compare(title, originaltitle, Qt::CaseInsensitive) == 0))
     229        {
     230            // In lookup by name, the television database tends to only include Banner artwork.
     231            // In lookup by name, the movie database tends to include only Fan and Cover artwork.
     232            if ((((*i)->GetArtwork(kArtworkFanart)).size() != 0) ||
     233                (((*i)->GetArtwork(kArtworkCoverart)).size() != 0) ||
     234                (((*i)->GetArtwork(kArtworkBanner)).size() != 0))
     235            {
     236                exactMatchesWithArt++;
     237            }
     238        }
     239    }
     240    return exactMatchesWithArt;
     241}
     242
    202243MetadataLookup* MetadataDownload::findBestMatch(MetadataLookupList list,
    203244                                            const QString &originaltitle) const
    204245{
    205246    QStringList titles;
    206247    MetadataLookup *ret = NULL;
     248    QDate exactTitleDate;
    207249
    208250    // Build a list of all the titles
    209251    int exactMatches = 0;
    210252    for (MetadataLookupList::const_iterator i = list.begin();
    211253            i != list.end(); ++i)
    212254    {
    213         QString title = (*i)->GetBaseTitle();
    214         if (title == originaltitle)
     255        QString title = (*i)->GetTitle();
     256        LOG(VB_GENERAL, LOG_INFO, QString("Comparing metadata title '%1' [%2] to recording title '%3'")
     257                .arg(title)
     258                .arg((*i)->GetReleaseDate().toString())
     259                .arg(originaltitle));
     260        // Consider exact title matches (ignoring case), which have some artwork available.
     261        if ((QString::compare(title, originaltitle, Qt::CaseInsensitive) == 0) &&
     262            ((((*i)->GetArtwork(kArtworkFanart)).size() != 0) ||
     263             (((*i)->GetArtwork(kArtworkCoverart)).size() != 0) ||
     264             (((*i)->GetArtwork(kArtworkBanner)).size() != 0)))
    215265        {
    216             ret = (*i);
     266            // We have an exact match on the title (ignoring case). After
     267            // the first exact match, prefer any more recently released one.
     268            if ((ret == NULL) || ((*i)->GetReleaseDate() > exactTitleDate))
     269            {
     270                exactTitleDate = (*i)->GetReleaseDate();
     271                ret = (*i);
     272            }
    217273            exactMatches++;
    218274        }
    219275
    MetadataLookup* MetadataDownload::findBestMatch(MetadataLookupList list, 
    226282    {
    227283        if (exactMatches == 1)
    228284        {
    229             LOG(VB_GENERAL, LOG_INFO, QString("Single Exact Title Match For %1")
     285            LOG(VB_GENERAL, LOG_INFO, QString("Single exact title match for '%1'")
    230286                    .arg(originaltitle));
    231             return ret;
    232287        }
    233288        else
    234289        {
    235             LOG(VB_GENERAL, LOG_ERR,
    236                 QString("Multiple exact title matches found for %1. "
    237                         "Need to match on other criteria.")
    238                     .arg(originaltitle));
    239             return NULL;
     290            LOG(VB_GENERAL, LOG_INFO,
     291                QString("Multiple exact title matches found for '%1'. "
     292                        "Selecting most recent [%2]")
     293                    .arg(originaltitle)
     294                    .arg(exactTitleDate.toString()));
    240295        }
     296        return ret;
    241297    }
    242298
    243299    // Apply Levenshtein distance algorithm to determine closest match
    MetadataLookup* MetadataDownload::findBestMatch(MetadataLookupList list, 
    260316    MetadataLookupList::const_iterator i = list.begin();
    261317    for (; i != list.end(); ++i)
    262318    {
    263         if ((*i)->GetBaseTitle() == bestTitle)
     319        if ((*i)->GetTitle() == bestTitle)
    264320        {
    265321            ret = (*i);
    266322            break;
    MetadataLookupList MetadataDownload::handleMovie(MetadataLookup *lookup) 
    534590        list = grabber.Search(lookup->GetBaseTitle(), lookup);
    535591    }
    536592
     593    // remove any list elements which are lacking artwork
     594    MetadataLookupList::const_iterator itr = list.begin();
     595    while (itr != list.end())
     596    {
     597        // In lookup by name, the movie database tends to include only Fan and Cover artwork.
     598        // However, this tendency may not be universal, so we'll look for any of the three
     599        // types of artwork.
     600        if ((((*itr)->GetArtwork(kArtworkFanart)).size() == 0) &&
     601            (((*itr)->GetArtwork(kArtworkCoverart)).size() == 0) &&
     602            (((*itr)->GetArtwork(kArtworkBanner)).size() == 0))
     603        {
     604            LOG(VB_GENERAL, LOG_INFO, QString("Removing '%1' entry with no artwork")
     605                    .arg((*itr)->GetTitle()));
     606            MetadataLookupList::const_iterator next_itr = itr;
     607            next_itr++;
     608            MetadataLookup *mdl = list.takeAt(itr - list.begin());
     609            if (mdl != NULL)
     610                delete(mdl);
     611            itr = next_itr;
     612        }
     613        else
     614            ++itr;
     615    }
     616
    537617    return list;
    538618}
    539619
    MetadataLookupList MetadataDownload::handleTelevision(MetadataLookup *lookup) 
    650730        }
    651731    }
    652732
     733    // remove any list elements which are lacking artwork
     734    MetadataLookupList::const_iterator itr = list.begin();
     735    while (itr != list.end())
     736    {
     737        // In lookup by name, the television database tends to include only Banner artwork.
     738        // However, this tendency may not be universal, so we'll look for any of the three
     739        // types of artwork.
     740        if ((((*itr)->GetArtwork(kArtworkFanart)).size() == 0) &&
     741            (((*itr)->GetArtwork(kArtworkCoverart)).size() == 0) &&
     742            (((*itr)->GetArtwork(kArtworkBanner)).size() == 0))
     743        {
     744            LOG(VB_GENERAL, LOG_INFO, QString("Removing '%1' entry with no artwork")
     745                    .arg((*itr)->GetTitle()));
     746            MetadataLookupList::const_iterator next_itr = itr;
     747            next_itr++;
     748            MetadataLookup *mdl = list.takeAt(itr - list.begin());
     749            if (mdl != NULL)
     750                delete(mdl);
     751            itr = next_itr;
     752        }
     753        else
     754            ++itr;
     755    }
     756
    653757    return list;
    654758}
    655759
  • mythtv/libs/libmythmetadata/metadatadownload.h

    diff --git a/mythtv/libs/libmythmetadata/metadatadownload.h b/mythtv/libs/libmythmetadata/metadatadownload.h
    index bc1030b..b585233 100644
    a b class META_PUBLIC MetadataDownload : public MThread 
    6767
    6868    MetadataLookupList  handleGame(MetadataLookup* lookup);
    6969
     70    unsigned int        findExactMatchWithArtCount(MetadataLookupList list,
     71                                                   const QString &originaltitle) const;
    7072    MetadataLookup*     findBestMatch(MetadataLookupList list,
    7173                                      const QString &originaltitle) const;
    7274    MetadataLookupList  runGrabber(QString cmd, QStringList args,
  • mythtv/programs/mythmetadatalookup/lookup.cpp

    diff --git a/mythtv/programs/mythmetadatalookup/lookup.cpp b/mythtv/programs/mythmetadatalookup/lookup.cpp
    index 6de23a1..eb3c2ab 100644
    a b void LookerUpper::customEvent(QEvent *levent) 
    246246        if (list.count() > 1)
    247247        {
    248248            int yearindex = -1;
     249            MetadataLookup *exactTitleMeta = NULL;
     250            QDate exactTitleDate;
    249251
    250252            for (int p = 0; p != list.size(); ++p)
    251253            {
    252254                ProgramInfo *pginfo = list[p]->GetData().value<ProgramInfo *>();
    253255
     256                if (pginfo && (QString::compare(pginfo->GetTitle(), list[p]->GetBaseTitle(), Qt::CaseInsensitive)) == 0)
     257                {
     258                    // We have an exact match on the title (ignoring case)
     259                    if ((exactTitleMeta == NULL) ||
     260                        (list[p]->GetReleaseDate() > exactTitleDate))
     261                    {
     262                        // remember the most recently released exact match
     263                        exactTitleDate = list[p]->GetReleaseDate();
     264                        exactTitleMeta = list[p];
     265                    }
     266                }
     267
    254268                if (pginfo && !pginfo->GetSeriesID().isEmpty() &&
    255269                    pginfo->GetSeriesID() == (list[p])->GetTMSref())
    256270                {
    void LookerUpper::customEvent(QEvent *levent) 
    291305                return;
    292306            }
    293307
     308            if (exactTitleMeta != NULL)
     309            {
     310                LOG(VB_GENERAL, LOG_INFO, QString("Most recent exact match released %1").arg(exactTitleDate.toString()));
     311                MetadataLookup *lookup = exactTitleMeta;
     312                ProgramInfo *pginfo = exactTitleMeta->GetData().value<ProgramInfo *>();
     313                if (lookup->GetSubtype() != kProbableGenericTelevision)
     314                    pginfo->SaveSeasonEpisode(lookup->GetSeason(), lookup->GetEpisode());
     315                pginfo->SaveInetRef(lookup->GetInetref());
     316                m_busyRecList.removeAll(pginfo);
     317                return;
     318            }
     319
    294320            LOG(VB_GENERAL, LOG_INFO, "Unable to match this title, too many possible matches. "
    295321                                      "You may wish to manually set the season, episode, and "
    296322                                      "inetref in the 'Watch Recordings' screen.");