Ticket #13159: mythtv-13159-PreferExactTitleMatchesForMetadata5.patch

File mythtv-13159-PreferExactTitleMatchesForMetadata5.patch, 17.4 KB (added by Steve Erlenborn <simon.sinister@…>, 9 years ago)

Updating Popularity references in videoLookupInfo.h

  • mythtv/libs/libmythmetadata/metadatacommon.cpp

    diff --git a/mythtv/libs/libmythmetadata/metadatacommon.cpp b/mythtv/libs/libmythmetadata/metadatacommon.cpp
    index d28d54e..9f25e76 100644
    a b MetadataLookup::MetadataLookup(  
    130130    uint subtitletype,
    131131    const QString &certification,
    132132    const QStringList &countries,
    133     const uint popularity,
     133    const float popularity,
    134134    const uint budget,
    135135    const uint revenue,
    136136    const QString &album,
    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()
    MetadataLookup* ParseMetadataItem(const QDomElement& item,  
    10021011
    10031012    uint season = 0, episode = 0, chanid = 0, programflags = 0,
    10041013         audioproperties = 0, videoproperties = 0, subtitletype = 0,
    1005          tracknum = 0, popularity = 0, budget = 0, revenue = 0,
     1014         tracknum = 0, budget = 0, revenue = 0,
    10061015         year = 0, runtime = 0, runtimesecs = 0, ratingcount = 0;
    10071016    QString title, network, status, subtitle, tagline, description, certification,
    10081017        channum, chansign, channame, chanplaybackfilters, recgroup,
    MetadataLookup* ParseMetadataItem(const QDomElement& item,  
    10101019        inetref, collectionref, tmsref, imdb, homepage, trailerURL, language;
    10111020    QStringList categories, countries, studios;
    10121021    float userrating = 0;
     1022    float popularity = 0;
    10131023    QDate releasedate;
    10141024    QDateTime lastupdated, startts, endts, recstartts, recendts;
    10151025    PeopleMap people;
    MetadataLookup* ParseMetadataItem(const QDomElement& item,  
    10641074    userrating = item.firstChildElement("userrating").text().toFloat();
    10651075    ratingcount = item.firstChildElement("ratingcount").text().toUInt();
    10661076    tracknum = item.firstChildElement("tracknum").text().toUInt();
    1067     popularity = item.firstChildElement("popularity").text().toUInt();
     1077    popularity = item.firstChildElement("popularity").text().toFloat();
    10681078    budget = item.firstChildElement("budget").text().toUInt();
    10691079    revenue = item.firstChildElement("revenue").text().toUInt();
    10701080    year = item.firstChildElement("year").text().toUInt();
  • mythtv/libs/libmythmetadata/metadatacommon.h

    diff --git a/mythtv/libs/libmythmetadata/metadatacommon.h b/mythtv/libs/libmythmetadata/metadatacommon.h
    index d0613e6..5ea18e9 100644
    a b class META_PUBLIC MetadataLookup : public QObject, public ReferenceCounter  
    130130        const uint subtitletype,
    131131        const QString &certification,
    132132        const QStringList &countries,
    133         const uint popularity,
     133        const float popularity,
    134134        const uint budget,
    135135        const uint revenue,
    136136        const QString &album,
    class META_PUBLIC MetadataLookup : public QObject, public ReferenceCounter  
    330330
    331331    QString GetCertification() const { return m_certification; };
    332332    QStringList GetCountries() const { return m_countries; };
    333     uint GetPopularity() const { return m_popularity; };
     333    float GetPopularity() const { return m_popularity; };
    334334    uint GetBudget() const { return m_budget; };
    335335    uint GetRevenue() const { return m_revenue; };
    336336
    class META_PUBLIC MetadataLookup : public QObject, public ReferenceCounter  
    417417
    418418    const QString m_certification;
    419419    const QStringList m_countries;
    420     uint m_popularity;
     420    float m_popularity;
    421421    uint m_budget;
    422422    uint m_revenue;
    423423
  • mythtv/libs/libmythmetadata/metadatadownload.cpp

    diff --git a/mythtv/libs/libmythmetadata/metadatadownload.cpp b/mythtv/libs/libmythmetadata/metadatadownload.cpp
    index bf5d4fb..24bc862 100644
    a b void MetadataDownload::run()  
    9797            lookup->GetType() == kMetadataRecording)
    9898        {
    9999            if (lookup->GetSubtype() == kProbableTelevision)
     100            {
    100101                list = handleTelevision(lookup);
     102                if (findExactMatchCount(list, lookup->GetBaseTitle(), true) == 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 (findExactMatchCount(list, lookup->GetBaseTitle(), true) == 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::findExactMatchCount(MetadataLookupList list,
     219                                                   const QString &originaltitle,
     220                                                   bool withArt) const
     221{
     222    unsigned int exactMatches = 0;
     223    unsigned int exactMatchesWithArt = 0;
     224
     225    for (MetadataLookupList::const_iterator i = list.begin();
     226            i != list.end(); ++i)
     227    {
     228        // Consider exact title matches (ignoring case)
     229        if ((QString::compare((*i)->GetTitle(), originaltitle, Qt::CaseInsensitive) == 0))
     230        {
     231            // In lookup by name, the television database tends to only include Banner artwork.
     232            // In lookup by name, the movie database tends to include only Fan and Cover artwork.
     233            if ((((*i)->GetArtwork(kArtworkFanart)).size() != 0) ||
     234                (((*i)->GetArtwork(kArtworkCoverart)).size() != 0) ||
     235                (((*i)->GetArtwork(kArtworkBanner)).size() != 0))
     236            {
     237                exactMatchesWithArt++;
     238            }
     239            exactMatches++;
     240        }
     241    }
     242
     243    if (withArt)
     244        return exactMatchesWithArt;
     245    else
     246        return exactMatches;
     247}
     248
    202249MetadataLookup* MetadataDownload::findBestMatch(MetadataLookupList list,
    203250                                            const QString &originaltitle) const
    204251{
    205252    QStringList titles;
    206253    MetadataLookup *ret = NULL;
     254    QDate exactTitleDate;
     255    float exactTitlePopularity;
     256    int exactMatches = 0;
     257    int exactMatchesWithArt = 0;
     258    bool foundMatchWithArt = false;
    207259
    208260    // Build a list of all the titles
    209     int exactMatches = 0;
    210261    for (MetadataLookupList::const_iterator i = list.begin();
    211262            i != list.end(); ++i)
    212263    {
    213         QString title = (*i)->GetBaseTitle();
    214         if (title == originaltitle)
     264        QString title = (*i)->GetTitle();
     265        LOG(VB_GENERAL, LOG_INFO, QString("Comparing metadata title '%1' [%2] to recording title '%3'")
     266                .arg(title)
     267                .arg((*i)->GetReleaseDate().toString())
     268                .arg(originaltitle));
     269        // Consider exact title matches (ignoring case), which have some artwork available.
     270        if (QString::compare(title, originaltitle, Qt::CaseInsensitive) == 0)
    215271        {
    216             ret = (*i);
     272            bool hasArtwork = ((((*i)->GetArtwork(kArtworkFanart)).size() != 0) ||
     273                               (((*i)->GetArtwork(kArtworkCoverart)).size() != 0) ||
     274                               (((*i)->GetArtwork(kArtworkBanner)).size() != 0));
     275
     276            LOG(VB_GENERAL, LOG_INFO, QString("'%1', popularity = %2, ReleaseDate = %3")
     277                    .arg(title)
     278                    .arg((*i)->GetPopularity())
     279                    .arg((*i)->GetReleaseDate().toString()));
     280
     281            // After the first exact match, prefer any more popular one.
     282            // Most of the Movie database entries have Popularity fields.
     283            // The TV series database generally has no Popularity values specified,
     284            // so if none are found so far in the search, pick the most recently
     285            // released entry with artwork. Also, if the first exact match had
     286            // no artwork, prefer any later exact match with artwork.
     287            if ((ret == NULL) ||
     288                (hasArtwork &&
     289                 ((!foundMatchWithArt) ||
     290                  (((*i)->GetPopularity() > exactTitlePopularity)) ||
     291                  ((exactTitlePopularity == 0.0) && ((*i)->GetReleaseDate() > exactTitleDate)))))
     292            {
     293                exactTitleDate = (*i)->GetReleaseDate();
     294                exactTitlePopularity = (*i)->GetPopularity();
     295                ret = (*i);
     296            }
    217297            exactMatches++;
     298            if (hasArtwork)
     299            {
     300                foundMatchWithArt = true;
     301                exactMatchesWithArt++;
     302            }
    218303        }
    219304
    220305        titles.append(title);
    221306    }
    222307
     308    LOG(VB_GENERAL, LOG_DEBUG, QString("exactMatches = %1, exactMatchesWithArt = %2")
     309            .arg(exactMatches)
     310            .arg(exactMatchesWithArt));
     311
    223312    // If there was one or more exact matches then we can skip a more intensive
    224313    // and time consuming search
    225314    if (exactMatches > 0)
    226315    {
    227316        if (exactMatches == 1)
    228317        {
    229             LOG(VB_GENERAL, LOG_INFO, QString("Single Exact Title Match For %1")
     318            LOG(VB_GENERAL, LOG_INFO, QString("Single exact title match for '%1'")
    230319                    .arg(originaltitle));
    231             return ret;
    232320        }
    233321        else
    234322        {
    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;
     323            LOG(VB_GENERAL, LOG_INFO,
     324                QString("Multiple exact title matches found for '%1'. "
     325                        "Selecting most popular or most recent [%2]")
     326                    .arg(originaltitle)
     327                    .arg(exactTitleDate.toString()));
    240328        }
     329        return ret;
    241330    }
    242331
    243332    // Apply Levenshtein distance algorithm to determine closest match
    MetadataLookup* MetadataDownload::findBestMatch(MetadataLookupList list,  
    260349    MetadataLookupList::const_iterator i = list.begin();
    261350    for (; i != list.end(); ++i)
    262351    {
    263         if ((*i)->GetBaseTitle() == bestTitle)
     352        if ((*i)->GetTitle() == bestTitle)
    264353        {
    265354            ret = (*i);
    266355            break;
  • mythtv/libs/libmythmetadata/metadatadownload.h

    diff --git a/mythtv/libs/libmythmetadata/metadatadownload.h b/mythtv/libs/libmythmetadata/metadatadownload.h
    index bc1030b..fc471a9 100644
    a b class META_PUBLIC MetadataDownload : public MThread  
    6767
    6868    MetadataLookupList  handleGame(MetadataLookup* lookup);
    6969
     70    unsigned int        findExactMatchCount(MetadataLookupList list,
     71                                      const QString &originaltitle,
     72                                      bool withArt) const;
    7073    MetadataLookup*     findBestMatch(MetadataLookupList list,
    7174                                      const QString &originaltitle) const;
    7275    MetadataLookupList  runGrabber(QString cmd, QStringList args,
  • mythtv/libs/libmythservicecontracts/datacontracts/videoLookupInfo.h

    diff --git a/mythtv/libs/libmythservicecontracts/datacontracts/videoLookupInfo.h b/mythtv/libs/libmythservicecontracts/datacontracts/videoLookupInfo.h
    index 051e668..95bd1ba 100644
    a b class SERVICE_PUBLIC VideoLookup : public QObject  
    9292    Q_PROPERTY( int             Length          READ Length           WRITE setLength         )
    9393    Q_PROPERTY( QString         Language        READ Language         WRITE setLanguage       )
    9494    Q_PROPERTY( QStringList     Countries       READ Countries        WRITE setCountries      )
    95     Q_PROPERTY( int             Popularity      READ Popularity       WRITE setPopularity     )
     95    Q_PROPERTY( float           Popularity      READ Popularity       WRITE setPopularity     )
    9696    Q_PROPERTY( int             Budget          READ Budget           WRITE setBudget         )
    9797    Q_PROPERTY( int             Revenue         READ Revenue          WRITE setRevenue        )
    9898    Q_PROPERTY( QString         IMDB            READ IMDB             WRITE setIMDB           )
    class SERVICE_PUBLIC VideoLookup : public QObject  
    116116    PROPERTYIMP    ( int        , Length         )
    117117    PROPERTYIMP    ( QString    , Language       )
    118118    PROPERTYIMP    ( QStringList, Countries      )
    119     PROPERTYIMP    ( int        , Popularity     )
     119    PROPERTYIMP    ( float      , Popularity     )
    120120    PROPERTYIMP    ( int        , Budget         )
    121121    PROPERTYIMP    ( int        , Revenue        )
    122122    PROPERTYIMP    ( QString    , IMDB           )
    class SERVICE_PUBLIC VideoLookup : public QObject  
    138138            m_Year             = 0                      ;
    139139            m_UserRating       = 0.0                    ;
    140140            m_Length           = 0.0                    ;
    141             m_Popularity       = 0                      ;
     141            m_Popularity       = 0.0                    ;
    142142            m_Budget           = 0                      ;
    143143            m_Revenue          = 0                      ;
    144144        }
  • mythtv/programs/mythmetadatalookup/lookup.cpp

    diff --git a/mythtv/programs/mythmetadatalookup/lookup.cpp b/mythtv/programs/mythmetadatalookup/lookup.cpp
    index 6de23a1..201cda6 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;
     251            float exactTitlePopularity = 0.0;
     252            bool foundMatchWithArt = false;
    249253
    250254            for (int p = 0; p != list.size(); ++p)
    251255            {
    252256                ProgramInfo *pginfo = list[p]->GetData().value<ProgramInfo *>();
    253257
     258                if (pginfo && (QString::compare(pginfo->GetTitle(), list[p]->GetBaseTitle(), Qt::CaseInsensitive)) == 0)
     259                {
     260                    bool hasArtwork = (((list[p]->GetArtwork(kArtworkFanart)).size() != 0) ||
     261                                       ((list[p]->GetArtwork(kArtworkCoverart)).size() != 0) ||
     262                                       ((list[p]->GetArtwork(kArtworkBanner)).size() != 0));
     263
     264                    // After the first exact match, prefer any more popular one.
     265                    // Most of the Movie database entries have Popularity fields.
     266                    // The TV series database generally has no Popularity values specified,
     267                    // so if none are found so far in the search, pick the most recently
     268                    // released entry with artwork. Also, if the first exact match had
     269                    // no artwork, prefer any later exact match with artwork.
     270                    if ((exactTitleMeta == NULL) ||
     271                        (hasArtwork &&
     272                         ((!foundMatchWithArt) ||
     273                          ((list[p]->GetPopularity() > exactTitlePopularity)) ||
     274                          ((exactTitlePopularity == 0.0) && (list[p]->GetReleaseDate() > exactTitleDate)))))
     275                    {
     276                        // remember the most popular or most recently released exact match
     277                        exactTitleDate = list[p]->GetReleaseDate();
     278                        exactTitlePopularity = list[p]->GetPopularity();
     279                        exactTitleMeta = list[p];
     280                    }
     281                }
     282
    254283                if (pginfo && !pginfo->GetSeriesID().isEmpty() &&
    255284                    pginfo->GetSeriesID() == (list[p])->GetTMSref())
    256285                {
    void LookerUpper::customEvent(QEvent *levent)  
    291320                return;
    292321            }
    293322
     323            if (exactTitleMeta != NULL)
     324            {
     325                LOG(VB_GENERAL, LOG_INFO, QString("Best match released %1").arg(exactTitleDate.toString()));
     326                MetadataLookup *lookup = exactTitleMeta;
     327                ProgramInfo *pginfo = exactTitleMeta->GetData().value<ProgramInfo *>();
     328                if (lookup->GetSubtype() != kProbableGenericTelevision)
     329                    pginfo->SaveSeasonEpisode(lookup->GetSeason(), lookup->GetEpisode());
     330                pginfo->SaveInetRef(lookup->GetInetref());
     331                m_busyRecList.removeAll(pginfo);
     332                return;
     333            }
     334
    294335            LOG(VB_GENERAL, LOG_INFO, "Unable to match this title, too many possible matches. "
    295336                                      "You may wish to manually set the season, episode, and "
    296337                                      "inetref in the 'Watch Recordings' screen.");