diff --git a/MediaBrowser.Controller/Entities/AdultVideo.cs b/MediaBrowser.Controller/Entities/AdultVideo.cs
index 9791f7cf79..00270accf1 100644
--- a/MediaBrowser.Controller/Entities/AdultVideo.cs
+++ b/MediaBrowser.Controller/Entities/AdultVideo.cs
@@ -3,7 +3,7 @@ using MediaBrowser.Controller.Providers;
namespace MediaBrowser.Controller.Entities
{
- public class AdultVideo : Video, IHasPreferredMetadataLanguage, IHasTaglines
+ public class AdultVideo : Video, IHasProductionLocations, IHasPreferredMetadataLanguage, IHasTaglines
{
///
/// Gets or sets the preferred metadata language.
@@ -16,12 +16,14 @@ namespace MediaBrowser.Controller.Entities
///
/// The preferred metadata country code.
public string PreferredMetadataCountryCode { get; set; }
+ public List ProductionLocations { get; set; }
public List Taglines { get; set; }
public AdultVideo()
{
Taglines = new List();
+ ProductionLocations = new List();
}
public override bool BeforeMetadataRefresh()
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index f53b676105..5510c795a0 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities.Movies
///
/// Class Movie
///
- public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasPreferredMetadataLanguage, IHasAwards, IHasMetascore, IHasLookupInfo, ISupportsBoxSetGrouping
+ public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasPreferredMetadataLanguage, IHasAwards, IHasMetascore, IHasLookupInfo, ISupportsBoxSetGrouping
{
public List SpecialFeatureIds { get; set; }
@@ -22,6 +22,7 @@ namespace MediaBrowser.Controller.Entities.Movies
public List ThemeSongIds { get; set; }
public List ThemeVideoIds { get; set; }
+ public List ProductionLocations { get; set; }
///
/// This is just a cache to enable quick access by Id
@@ -48,6 +49,7 @@ namespace MediaBrowser.Controller.Entities.Movies
BoxSetIdList = new List();
Taglines = new List();
Keywords = new List();
+ ProductionLocations = new List();
}
public string AwardSummary { get; set; }
diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs
index 554914ec6b..bbb2bc8755 100644
--- a/MediaBrowser.Controller/Entities/MusicVideo.cs
+++ b/MediaBrowser.Controller/Entities/MusicVideo.cs
@@ -9,7 +9,7 @@ using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities
{
- public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasBudget, IHasLookupInfo
+ public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasProductionLocations, IHasBudget, IHasLookupInfo
{
///
/// Gets or sets the artist.
@@ -34,6 +34,12 @@ namespace MediaBrowser.Controller.Entities
///
/// The revenue.
public double? Revenue { get; set; }
+ public List ProductionLocations { get; set; }
+
+ public MusicVideo()
+ {
+ ProductionLocations = new List();
+ }
[IgnoreDataMember]
public List AllArtists
diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs
index 53ec030a78..569334ec3f 100644
--- a/MediaBrowser.Controller/Entities/Trailer.cs
+++ b/MediaBrowser.Controller/Entities/Trailer.cs
@@ -12,11 +12,12 @@ namespace MediaBrowser.Controller.Entities
///
/// Class Trailer
///
- public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers, IHasKeywords, IHasTaglines, IHasPreferredMetadataLanguage, IHasMetascore, IHasLookupInfo
+ public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasTrailers, IHasKeywords, IHasTaglines, IHasPreferredMetadataLanguage, IHasMetascore, IHasLookupInfo
{
public List SoundtrackIds { get; set; }
public string PreferredMetadataLanguage { get; set; }
+ public List ProductionLocations { get; set; }
///
/// Gets or sets the preferred metadata country code.
@@ -31,6 +32,7 @@ namespace MediaBrowser.Controller.Entities
SoundtrackIds = new List();
LocalTrailerIds = new List();
Keywords = new List();
+ ProductionLocations = new List();
}
public float? Metascore { get; set; }
diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
index a6714f6561..41f994303b 100644
--- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
+++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
@@ -62,34 +62,6 @@ namespace MediaBrowser.Controller.Providers
ValidationType = ValidationType.None
};
- var hasTaglines = item as IHasTaglines;
- if (hasTaglines != null)
- {
- hasTaglines.Taglines.Clear();
- }
-
- item.Studios.Clear();
- item.Genres.Clear();
- item.People.Clear();
-
- var hasTags = item as IHasTags;
- if (hasTags != null)
- {
- hasTags.Tags.Clear();
- }
-
- var hasKeywords = item as IHasKeywords;
- if (hasKeywords != null)
- {
- hasKeywords.Keywords.Clear();
- }
-
- var hasTrailers = item as IHasTrailers;
- if (hasTrailers != null)
- {
- hasTrailers.RemoteTrailers.Clear();
- }
-
//Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken);
Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken);
}
@@ -373,6 +345,15 @@ namespace MediaBrowser.Controller.Providers
break;
}
+ case "Countries":
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchFromCountriesNode(subtree, item);
+ }
+ break;
+ }
+
case "ContentRating":
case "MPAARating":
{
@@ -857,6 +838,42 @@ namespace MediaBrowser.Controller.Providers
}
}
+ private void FetchFromCountriesNode(XmlReader reader, T item)
+ {
+ reader.MoveToContent();
+
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Country":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ var hasProductionLocations = item as IHasProductionLocations;
+ if (hasProductionLocations != null)
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ hasProductionLocations.AddProductionLocation(val);
+ }
+ }
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
+
///
/// Fetches from taglines node.
///
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 43402123cb..ce5f8aa28b 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -109,6 +109,7 @@
+
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
index 7318fd17a9..9041d5a92c 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
@@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.MediaInfo
{
var prober = new FFProbeVideoInfo(_logger, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem, _config, _subtitleManager);
- return !video.SubtitleFiles.SequenceEqual(prober.GetSubtitleFiles(video, directoryService, false).Select(i => i.FullName).OrderBy(i => i), StringComparer.OrdinalIgnoreCase);
+ return !video.SubtitleFiles.SequenceEqual(SubtitleResolver.GetSubtitleFiles(video, directoryService, false).Select(i => i.FullName).OrderBy(i => i), StringComparer.OrdinalIgnoreCase);
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index 76b0818fe9..5ce53378cb 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -411,50 +411,6 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- private IEnumerable SubtitleExtensions
- {
- get
- {
- return new[] { ".srt", ".ssa", ".ass", ".sub" };
- }
- }
-
- public IEnumerable GetSubtitleFiles(Video video, IDirectoryService directoryService, bool clearCache)
- {
- var containingPath = video.ContainingFolderPath;
-
- if (string.IsNullOrEmpty(containingPath))
- {
- throw new ArgumentException(string.Format("Cannot search for items that don't have a path: {0} {1}", video.Name, video.Id));
- }
-
- var files = directoryService.GetFiles(containingPath, clearCache);
-
- var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
-
- return files.Where(i =>
- {
- if (!i.Attributes.HasFlag(FileAttributes.Directory) &&
- SubtitleExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
- {
- var fullName = i.FullName;
-
- var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
-
- if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- }
-
- return false;
- });
- }
-
///
/// Adds the external subtitles.
///
@@ -462,7 +418,9 @@ namespace MediaBrowser.Providers.MediaInfo
/// The current streams.
private async Task AddExternalSubtitles(Video video, List currentStreams, IDirectoryService directoryService, CancellationToken cancellationToken)
{
- var externalSubtitleStreams = GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, false).ToList();
+ var subtitleResolver = new SubtitleResolver(_localization);
+
+ var externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, false).ToList();
if ((_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles &&
video is Episode) ||
@@ -482,7 +440,7 @@ namespace MediaBrowser.Providers.MediaInfo
// Rescan
if (downloadedLanguages.Count > 0)
{
- externalSubtitleStreams = GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, true).ToList();
+ externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, true).ToList();
}
}
@@ -491,65 +449,6 @@ namespace MediaBrowser.Providers.MediaInfo
currentStreams.AddRange(externalSubtitleStreams);
}
- private IEnumerable GetExternalSubtitleStreams(Video video,
- int startIndex,
- IDirectoryService directoryService,
- bool clearCache)
- {
- var files = GetSubtitleFiles(video, directoryService, clearCache);
-
- var streams = new List();
-
- var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
-
- foreach (var file in files)
- {
- var fullName = file.FullName;
-
- var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
-
- // If the subtitle file matches the video file name
- if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
- {
- streams.Add(new MediaStream
- {
- Index = startIndex++,
- Type = MediaStreamType.Subtitle,
- IsExternal = true,
- Path = fullName,
- Codec = Path.GetExtension(fullName).ToLower().TrimStart('.')
- });
- }
- else if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
- {
- // Support xbmc naming conventions - 300.spanish.srt
- var language = fileNameWithoutExtension.Split('.').LastOrDefault();
-
- // Try to translate to three character code
- // Be flexible and check against both the full and three character versions
- var culture = _localization.GetCultures()
- .FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase));
-
- if (culture != null)
- {
- language = culture.ThreeLetterISOLanguageName;
- }
-
- streams.Add(new MediaStream
- {
- Index = startIndex++,
- Type = MediaStreamType.Subtitle,
- IsExternal = true,
- Path = fullName,
- Codec = Path.GetExtension(fullName).ToLower().TrimStart('.'),
- Language = language
- });
- }
- }
-
- return streams;
- }
-
///
/// The dummy chapter duration
///
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
new file mode 100644
index 0000000000..c12f74fa61
--- /dev/null
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
@@ -0,0 +1,135 @@
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Localization;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace MediaBrowser.Providers.MediaInfo
+{
+ public class SubtitleResolver
+ {
+ private readonly ILocalizationManager _localization;
+
+ public SubtitleResolver(ILocalizationManager localization)
+ {
+ _localization = localization;
+ }
+
+ public IEnumerable GetExternalSubtitleStreams(Video video,
+ int startIndex,
+ IDirectoryService directoryService,
+ bool clearCache)
+ {
+ var files = GetSubtitleFiles(video, directoryService, clearCache);
+
+ var streams = new List();
+
+ var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
+
+ foreach (var file in files)
+ {
+ var fullName = file.FullName;
+
+ var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
+
+ var codec = Path.GetExtension(fullName).ToLower().TrimStart('.');
+
+ // If the subtitle file matches the video file name
+ if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
+ {
+ streams.Add(new MediaStream
+ {
+ Index = startIndex++,
+ Type = MediaStreamType.Subtitle,
+ IsExternal = true,
+ Path = fullName,
+ Codec = codec
+ });
+ }
+ else if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
+ {
+ var isForced = fullName.IndexOf(".forced.", StringComparison.OrdinalIgnoreCase) != -1 ||
+ fullName.IndexOf(".foreign.", StringComparison.OrdinalIgnoreCase) != -1;
+
+ // Support xbmc naming conventions - 300.spanish.srt
+ var language = fileNameWithoutExtension
+ .Replace(".forced", string.Empty, StringComparison.OrdinalIgnoreCase)
+ .Replace(".foreign", string.Empty, StringComparison.OrdinalIgnoreCase)
+ .Split('.')
+ .LastOrDefault();
+
+ // Try to translate to three character code
+ // Be flexible and check against both the full and three character versions
+ var culture = _localization.GetCultures()
+ .FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase));
+
+ if (culture != null)
+ {
+ language = culture.ThreeLetterISOLanguageName;
+ }
+
+ streams.Add(new MediaStream
+ {
+ Index = startIndex++,
+ Type = MediaStreamType.Subtitle,
+ IsExternal = true,
+ Path = fullName,
+ Codec = codec,
+ Language = language,
+ IsForced = isForced
+ });
+ }
+ }
+
+ return streams;
+ }
+
+ private static IEnumerable SubtitleExtensions
+ {
+ get
+ {
+ return new[] { ".srt", ".ssa", ".ass", ".sub" };
+ }
+ }
+
+ public static IEnumerable GetSubtitleFiles(Video video, IDirectoryService directoryService, bool clearCache)
+ {
+ var containingPath = video.ContainingFolderPath;
+
+ if (string.IsNullOrEmpty(containingPath))
+ {
+ throw new ArgumentException(string.Format("Cannot search for items that don't have a path: {0} {1}", video.Name, video.Id));
+ }
+
+ var files = directoryService.GetFiles(containingPath, clearCache);
+
+ var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
+
+ return files.Where(i =>
+ {
+ if (!i.Attributes.HasFlag(FileAttributes.Directory) &&
+ SubtitleExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
+ {
+ var fullName = i.FullName;
+
+ var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
+
+ if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ });
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
index bf2be654b4..34e535a852 100644
--- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
+++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
@@ -133,6 +133,18 @@ namespace MediaBrowser.Providers.Movies
}
}
+ if (movieData.production_countries != null)
+ {
+ var hasProductionLocations = movie as IHasProductionLocations;
+ if (hasProductionLocations != null)
+ {
+ hasProductionLocations.ProductionLocations = movieData
+ .production_countries
+ .Select(i => i.name)
+ .ToList();
+ }
+ }
+
movie.SetProviderId(MetadataProviders.Tmdb, movieData.id.ToString(_usCulture));
movie.SetProviderId(MetadataProviders.Imdb, movieData.imdb_id);
diff --git a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
index 679a1f5303..7241dedcae 100644
--- a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
+++ b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
@@ -34,6 +34,7 @@ namespace MediaBrowser.Providers.Savers
"Chapters",
"ContentRating",
+ "Countries",
"CustomRating",
"CriticRating",
"CriticRatingSummary",
@@ -318,6 +319,22 @@ namespace MediaBrowser.Providers.Savers
}
}
+ var hasProductionLocations = item as IHasProductionLocations;
+ if (hasProductionLocations != null)
+ {
+ if (hasProductionLocations.ProductionLocations.Count > 0)
+ {
+ builder.Append("");
+
+ foreach (var name in hasProductionLocations.ProductionLocations)
+ {
+ builder.Append("" + SecurityElement.Escape(name) + "");
+ }
+
+ builder.Append("");
+ }
+ }
+
var hasDisplayOrder = item as IHasDisplayOrder;
if (hasDisplayOrder != null && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder))
{
diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs
index 639a65727f..158d1eccd3 100644
--- a/MediaBrowser.WebDashboard/Api/DashboardService.cs
+++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs
@@ -549,7 +549,6 @@ namespace MediaBrowser.WebDashboard.Api
"dlnaserversettings.js",
"editcollectionitems.js",
"edititemmetadata.js",
- "edititempeople.js",
"edititemimages.js",
"encodingsettings.js",
"gamesrecommendedpage.js",
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 7755145ee9..b22a95a376 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -391,9 +391,6 @@
PreserveNewest
-
- PreserveNewest
-
PreserveNewest
@@ -1450,9 +1447,6 @@
PreserveNewest
-
- PreserveNewest
-
PreserveNewest