Ticket #13159: mythtv-13159-PreferExactTitleMatchesForMetadata5.patch
File mythtv-13159-PreferExactTitleMatchesForMetadata5.patch, 17.4 KB (added by , 6 years ago) |
---|
-
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( 130 130 uint subtitletype, 131 131 const QString &certification, 132 132 const QStringList &countries, 133 const uint popularity,133 const float popularity, 134 134 const uint budget, 135 135 const uint revenue, 136 136 const QString &album, … … MetadataLookup::MetadataLookup( 219 219 m_artwork(artwork), 220 220 m_downloads(downloads) 221 221 { 222 QString manRecSuffix = QString(" (%1)").arg(QObject::tr("Manual Record")); 223 m_base_title = title; 224 m_base_title.replace(manRecSuffix,""); 222 225 } 223 226 224 227 // ProgramInfo-style constructor … … MetadataLookup::MetadataLookup( 312 315 m_popularity = 0; 313 316 m_budget = 0; 314 317 m_revenue = 0; 318 QString manRecSuffix = QString(" (%1)").arg(QObject::tr("Manual Record")); 319 m_base_title = title; 320 m_base_title.replace(manRecSuffix,""); 315 321 } 316 322 317 323 // XBMC NFO-style constructor … … MetadataLookup::MetadataLookup( 388 394 m_artwork(artwork), 389 395 m_downloads(downloads) 390 396 { 397 QString manRecSuffix = QString(" (%1)").arg(QObject::tr("Manual Record")); 398 m_base_title = title; 399 m_base_title.replace(manRecSuffix,""); 391 400 } 392 401 393 402 MetadataLookup::~MetadataLookup() … … MetadataLookup* ParseMetadataItem(const QDomElement& item, 1002 1011 1003 1012 uint season = 0, episode = 0, chanid = 0, programflags = 0, 1004 1013 audioproperties = 0, videoproperties = 0, subtitletype = 0, 1005 tracknum = 0, popularity = 0,budget = 0, revenue = 0,1014 tracknum = 0, budget = 0, revenue = 0, 1006 1015 year = 0, runtime = 0, runtimesecs = 0, ratingcount = 0; 1007 1016 QString title, network, status, subtitle, tagline, description, certification, 1008 1017 channum, chansign, channame, chanplaybackfilters, recgroup, … … MetadataLookup* ParseMetadataItem(const QDomElement& item, 1010 1019 inetref, collectionref, tmsref, imdb, homepage, trailerURL, language; 1011 1020 QStringList categories, countries, studios; 1012 1021 float userrating = 0; 1022 float popularity = 0; 1013 1023 QDate releasedate; 1014 1024 QDateTime lastupdated, startts, endts, recstartts, recendts; 1015 1025 PeopleMap people; … … MetadataLookup* ParseMetadataItem(const QDomElement& item, 1064 1074 userrating = item.firstChildElement("userrating").text().toFloat(); 1065 1075 ratingcount = item.firstChildElement("ratingcount").text().toUInt(); 1066 1076 tracknum = item.firstChildElement("tracknum").text().toUInt(); 1067 popularity = item.firstChildElement("popularity").text().to UInt();1077 popularity = item.firstChildElement("popularity").text().toFloat(); 1068 1078 budget = item.firstChildElement("budget").text().toUInt(); 1069 1079 revenue = item.firstChildElement("revenue").text().toUInt(); 1070 1080 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 130 130 const uint subtitletype, 131 131 const QString &certification, 132 132 const QStringList &countries, 133 const uint popularity,133 const float popularity, 134 134 const uint budget, 135 135 const uint revenue, 136 136 const QString &album, … … class META_PUBLIC MetadataLookup : public QObject, public ReferenceCounter 330 330 331 331 QString GetCertification() const { return m_certification; }; 332 332 QStringList GetCountries() const { return m_countries; }; 333 uint GetPopularity() const { return m_popularity; };333 float GetPopularity() const { return m_popularity; }; 334 334 uint GetBudget() const { return m_budget; }; 335 335 uint GetRevenue() const { return m_revenue; }; 336 336 … … class META_PUBLIC MetadataLookup : public QObject, public ReferenceCounter 417 417 418 418 const QString m_certification; 419 419 const QStringList m_countries; 420 uint m_popularity;420 float m_popularity; 421 421 uint m_budget; 422 422 uint m_revenue; 423 423 -
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() 97 97 lookup->GetType() == kMetadataRecording) 98 98 { 99 99 if (lookup->GetSubtype() == kProbableTelevision) 100 { 100 101 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 } 101 109 else if (lookup->GetSubtype() == kProbableMovie) 110 { 102 111 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 } 103 119 else 104 120 { 105 121 // will try both movie and TV … … void MetadataDownload::run() 199 215 RunEpilog(); 200 216 } 201 217 218 unsigned 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 202 249 MetadataLookup* MetadataDownload::findBestMatch(MetadataLookupList list, 203 250 const QString &originaltitle) const 204 251 { 205 252 QStringList titles; 206 253 MetadataLookup *ret = NULL; 254 QDate exactTitleDate; 255 float exactTitlePopularity; 256 int exactMatches = 0; 257 int exactMatchesWithArt = 0; 258 bool foundMatchWithArt = false; 207 259 208 260 // Build a list of all the titles 209 int exactMatches = 0;210 261 for (MetadataLookupList::const_iterator i = list.begin(); 211 262 i != list.end(); ++i) 212 263 { 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) 215 271 { 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 } 217 297 exactMatches++; 298 if (hasArtwork) 299 { 300 foundMatchWithArt = true; 301 exactMatchesWithArt++; 302 } 218 303 } 219 304 220 305 titles.append(title); 221 306 } 222 307 308 LOG(VB_GENERAL, LOG_DEBUG, QString("exactMatches = %1, exactMatchesWithArt = %2") 309 .arg(exactMatches) 310 .arg(exactMatchesWithArt)); 311 223 312 // If there was one or more exact matches then we can skip a more intensive 224 313 // and time consuming search 225 314 if (exactMatches > 0) 226 315 { 227 316 if (exactMatches == 1) 228 317 { 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'") 230 319 .arg(originaltitle)); 231 return ret;232 320 } 233 321 else 234 322 { 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())); 240 328 } 329 return ret; 241 330 } 242 331 243 332 // Apply Levenshtein distance algorithm to determine closest match … … MetadataLookup* MetadataDownload::findBestMatch(MetadataLookupList list, 260 349 MetadataLookupList::const_iterator i = list.begin(); 261 350 for (; i != list.end(); ++i) 262 351 { 263 if ((*i)->Get BaseTitle() == bestTitle)352 if ((*i)->GetTitle() == bestTitle) 264 353 { 265 354 ret = (*i); 266 355 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 67 67 68 68 MetadataLookupList handleGame(MetadataLookup* lookup); 69 69 70 unsigned int findExactMatchCount(MetadataLookupList list, 71 const QString &originaltitle, 72 bool withArt) const; 70 73 MetadataLookup* findBestMatch(MetadataLookupList list, 71 74 const QString &originaltitle) const; 72 75 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 92 92 Q_PROPERTY( int Length READ Length WRITE setLength ) 93 93 Q_PROPERTY( QString Language READ Language WRITE setLanguage ) 94 94 Q_PROPERTY( QStringList Countries READ Countries WRITE setCountries ) 95 Q_PROPERTY( intPopularity READ Popularity WRITE setPopularity )95 Q_PROPERTY( float Popularity READ Popularity WRITE setPopularity ) 96 96 Q_PROPERTY( int Budget READ Budget WRITE setBudget ) 97 97 Q_PROPERTY( int Revenue READ Revenue WRITE setRevenue ) 98 98 Q_PROPERTY( QString IMDB READ IMDB WRITE setIMDB ) … … class SERVICE_PUBLIC VideoLookup : public QObject 116 116 PROPERTYIMP ( int , Length ) 117 117 PROPERTYIMP ( QString , Language ) 118 118 PROPERTYIMP ( QStringList, Countries ) 119 PROPERTYIMP ( int, Popularity )119 PROPERTYIMP ( float , Popularity ) 120 120 PROPERTYIMP ( int , Budget ) 121 121 PROPERTYIMP ( int , Revenue ) 122 122 PROPERTYIMP ( QString , IMDB ) … … class SERVICE_PUBLIC VideoLookup : public QObject 138 138 m_Year = 0 ; 139 139 m_UserRating = 0.0 ; 140 140 m_Length = 0.0 ; 141 m_Popularity = 0 141 m_Popularity = 0.0 ; 142 142 m_Budget = 0 ; 143 143 m_Revenue = 0 ; 144 144 } -
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) 246 246 if (list.count() > 1) 247 247 { 248 248 int yearindex = -1; 249 MetadataLookup *exactTitleMeta = NULL; 250 QDate exactTitleDate; 251 float exactTitlePopularity = 0.0; 252 bool foundMatchWithArt = false; 249 253 250 254 for (int p = 0; p != list.size(); ++p) 251 255 { 252 256 ProgramInfo *pginfo = list[p]->GetData().value<ProgramInfo *>(); 253 257 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 254 283 if (pginfo && !pginfo->GetSeriesID().isEmpty() && 255 284 pginfo->GetSeriesID() == (list[p])->GetTMSref()) 256 285 { … … void LookerUpper::customEvent(QEvent *levent) 291 320 return; 292 321 } 293 322 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 294 335 LOG(VB_GENERAL, LOG_INFO, "Unable to match this title, too many possible matches. " 295 336 "You may wish to manually set the season, episode, and " 296 337 "inetref in the 'Watch Recordings' screen.");