Skip to content

Commit a4e12dd

Browse files
committed
Harmonize Title-Parsing of Movies and TV-Series
This change respects parentheses, i.e.: curved marks "()" in the parsed filenames of a movie, thus parsing of the release year in parentheses will work. It enables MythTV's movie grabber to extract the release year from the parsed filename and do a search for title with year. The correct syntax for a filename is from now on "A Movie Title (YYYY).mpg" instead of "A Movie Title YYYY.mpg" as stated in the wiki. It resolves ambiguous parsing of different movie titles like `Wonder Woman 1984` and `Wonder Woman`. Note: For tv-series, it is already allowed to add the year in the title, like `The Forsyte Saga (1967)` e.g.: `The Forsyte Saga (1967) 01x01 A Family Festival.mkv` is correctly parsed. Fixes #974
1 parent cda772e commit a4e12dd

File tree

3 files changed

+60
-16
lines changed

3 files changed

+60
-16
lines changed

mythtv/bindings/python/tmdb3/tmdb3/lookup.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#-----------------------
1313
__title__ = "TheMovieDB.org V3"
1414
__author__ = "Raymond Wagner, Roland Ernst"
15-
__version__ = "0.3.11"
15+
__version__ = "0.3.12"
1616
# 0.1.0 Initial version
1717
# 0.2.0 Add language support, move cache to home directory
1818
# 0.3.0 Enable version detection to allow use in MythTV
@@ -32,6 +32,7 @@
3232
# 0.3.9 Support TV lookup
3333
# 0.3.10 Use new API for release dates for movies
3434
# 0.3.11 Allow queries for specials in series in TV lookup
35+
# 0.3.12 `buildMovieList` searches now for movies with year
3536

3637
# ~ from optparse import OptionParser
3738
import sys
@@ -189,10 +190,10 @@ def buildMovieList(query, opts):
189190
# as negative to all text that comes afterwards
190191
query = query.replace('-',' ')
191192

192-
from MythTV.tmdb3 import searchMovie
193+
from MythTV.tmdb3 import searchMovieWithYear
193194
from MythTV import VideoMetadata
194195
from lxml import etree
195-
results = iter(searchMovie(query))
196+
results = iter(searchMovieWithYear(query))
196197
tree = etree.XML('<metadata></metadata>')
197198
mapping = [['runtime', 'runtime'], ['title', 'originaltitle'],
198199
['releasedate', 'releasedate'], ['tagline', 'tagline'],

mythtv/libs/libmythmetadata/metadatadownload.cpp

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <QEvent>
77
#include <QDir>
88
#include <QUrl>
9+
#include <QRegularExpression>
910

1011
// myth
1112
#include "libmythbase/mythcorecontext.h"
@@ -199,7 +200,7 @@ void MetadataDownload::run()
199200
MetadataLookup *newlookup = list.takeFirst();
200201

201202
// pass through automatic type
202-
newlookup->SetAutomatic(true); // ### XXX RER
203+
newlookup->SetAutomatic(true);
203204
newlookup->SetStep(kLookupData);
204205
// Type may have changed
205206
LookupType ret = GuessLookupType(newlookup);
@@ -252,11 +253,20 @@ unsigned int MetadataDownload::findExactMatchCount(MetadataLookupList list,
252253
{
253254
unsigned int exactMatches = 0;
254255
unsigned int exactMatchesWithArt = 0;
256+
static const QRegularExpression year { R"( \(\d{4}\)$)" };
255257

256258
for (const auto& lkup : std::as_const(list))
257259
{
258-
// Consider exact title matches (ignoring case)
259-
if ((QString::compare(lkup->GetTitle(), originaltitle, Qt::CaseInsensitive) == 0))
260+
// Consider exact title matches with or without trailing '(year)' (ignoring case)
261+
QString titlewoyear = originaltitle;
262+
auto match = year.match(titlewoyear);
263+
if (match.hasMatch())
264+
{
265+
titlewoyear.remove(match.capturedStart(), match.capturedLength());
266+
}
267+
268+
if ((QString::compare(lkup->GetTitle(), originaltitle, Qt::CaseInsensitive) == 0) ||
269+
(QString::compare(lkup->GetTitle(), titlewoyear, Qt::CaseInsensitive) == 0))
260270
{
261271
// In lookup by name, the television database tends to only include Banner artwork.
262272
// In lookup by name, the movie database tends to include only Fan and Cover artwork.
@@ -285,33 +295,63 @@ MetadataLookup* MetadataDownload::findBestMatch(MetadataLookupList list,
285295
int exactMatches = 0;
286296
int exactMatchesWithArt = 0;
287297
bool foundMatchWithArt = false;
298+
bool foundMatchWithYear = false;
299+
uint year = 0;
300+
301+
QString titlewoyear = originaltitle;
302+
303+
static const QRegularExpression regexyear { R"( \(\d{4}\)$)" };
304+
305+
auto match = regexyear.match(titlewoyear);
306+
if (match.hasMatch())
307+
{
308+
titlewoyear.remove(match.capturedStart(), match.capturedLength());
309+
year = match.captured(0).replace(" (","").replace(")","").toUInt();
310+
LOG(VB_GENERAL, LOG_DEBUG, QString("Looking for: '%1' with release year: '%2'")
311+
.arg(titlewoyear, QString::number(year)));
312+
}
288313

289314
// Build a list of all the titles
290315
for (const auto& lkup : std::as_const(list))
291316
{
292317
QString title = lkup->GetTitle();
293-
LOG(VB_GENERAL, LOG_INFO, QString("Comparing metadata title '%1' [%2] to recording title '%3'")
294-
.arg(title, lkup->GetReleaseDate().toString(), originaltitle));
295-
// Consider exact title matches (ignoring case), which have some artwork available.
296-
if (QString::compare(title, originaltitle, Qt::CaseInsensitive) == 0)
318+
LOG(VB_GENERAL, LOG_INFO,
319+
QString("Comparing metadata title '%1' [%2] to recording title '%3' [%4]")
320+
.arg(title, lkup->GetReleaseDate().toString(), titlewoyear,
321+
(year == 0) ? "N/A" : QString::number(year)));
322+
323+
// Consider exact title matches with or without trailing '(year)' (ignoring case),
324+
// which have some artwork available.
325+
if ((QString::compare(title, originaltitle, Qt::CaseInsensitive) == 0) ||
326+
(QString::compare(title, titlewoyear, Qt::CaseInsensitive) == 0))
297327
{
298328
bool hasArtwork = ((!(lkup->GetArtwork(kArtworkFanart)).empty()) ||
299329
(!(lkup->GetArtwork(kArtworkCoverart)).empty()) ||
300330
(!(lkup->GetArtwork(kArtworkBanner)).empty()));
301331

302-
LOG(VB_GENERAL, LOG_INFO, QString("'%1', popularity = %2, ReleaseDate = %3")
332+
if ((lkup->GetYear() != 0) && (year == lkup->GetYear()))
333+
{
334+
exactTitleDate = lkup->GetReleaseDate();
335+
exactTitlePopularity = lkup->GetPopularity();
336+
foundMatchWithYear = true;
337+
ret = lkup;
338+
}
339+
340+
LOG(VB_GENERAL, LOG_INFO, QString("'%1', popularity = %2, ReleaseDate = %3, Year = %4")
303341
.arg(title)
304342
.arg(lkup->GetPopularity())
305-
.arg(lkup->GetReleaseDate().toString()));
343+
.arg(lkup->GetReleaseDate().toString())
344+
.arg(lkup->GetYear()));
306345

307346
// After the first exact match, prefer any more popular one.
308347
// Most of the Movie database entries have Popularity fields.
309348
// The TV series database generally has no Popularity values specified,
310349
// so if none are found so far in the search, pick the most recently
311350
// released entry with artwork. Also, if the first exact match had
312351
// no artwork, prefer any later exact match with artwork.
352+
// Stop searching if we have already found a match with correct year.
313353
if ((ret == nullptr) ||
314-
(hasArtwork &&
354+
(hasArtwork && !foundMatchWithYear &&
315355
((!foundMatchWithArt) ||
316356
((lkup->GetPopularity() > exactTitlePopularity)) ||
317357
((exactTitlePopularity == 0.0F) && (lkup->GetReleaseDate() > exactTitleDate)))))
@@ -320,6 +360,7 @@ MetadataLookup* MetadataDownload::findBestMatch(MetadataLookupList list,
320360
exactTitlePopularity = lkup->GetPopularity();
321361
ret = lkup;
322362
}
363+
323364
exactMatches++;
324365
if (hasArtwork)
325366
{
@@ -348,8 +389,10 @@ MetadataLookup* MetadataDownload::findBestMatch(MetadataLookupList list,
348389
{
349390
LOG(VB_GENERAL, LOG_INFO,
350391
QString("Multiple exact title matches found for '%1'. "
351-
"Selecting most popular or most recent [%2]")
352-
.arg(originaltitle, exactTitleDate.toString()));
392+
"Selecting by exact year [%2] or most popular or most recent [%3]")
393+
.arg(originaltitle,
394+
(year == 0) ? "N/A" : QString::number(year),
395+
exactTitleDate.toString()));
353396
}
354397
return ret;
355398
}

mythtv/libs/libmythmetadata/videometadata.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1210,8 +1210,8 @@ QString VideoMetadata::FilenameToMeta(const QString &file_name, int position)
12101210
title = title.right(title.length() -
12111211
title.lastIndexOf('/') -1);
12121212

1213+
// Allow parentheses "()", but remove content inside other braces
12131214
title = eatBraces(title, "[", "]");
1214-
title = eatBraces(title, "(", ")");
12151215
title = eatBraces(title, "{", "}");
12161216
return title.trimmed();
12171217
}

0 commit comments

Comments
 (0)