diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 9d394fac6..fdd24e76b 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1064,6 +1064,8 @@ namespace MediaBrowser.Controller.Entities { try { + Logger.Debug("Found shortcut at {0}", i.FullName); + return new LinkedChild { Path = FileSystem.ResolveShortcut(i.FullName), @@ -1082,6 +1084,7 @@ namespace MediaBrowser.Controller.Entities if (!newShortcutLinks.SequenceEqual(currentShortcutLinks)) { Logger.Info("Shortcut links have changed for {0}", Path); + newShortcutLinks.AddRange(currentManualLinks); LinkedChildren = newShortcutLinks; return true; diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index b290d3bb5..357b38ecf 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -235,6 +235,35 @@ namespace MediaBrowser.Controller.Providers break; } + case "LockedFields": + { + var fields = new List(); + + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + var list = val.Split('|').Select(i => + { + MetadataFields field; + + if (Enum.TryParse(i, true, out field)) + { + return (MetadataFields?)field; + } + + return null; + + }).Where(i => i.HasValue).Select(i => i.Value); + + fields.AddRange(list); + } + + item.LockedFields = fields; + + break; + } + case "TagLines": { FetchFromTaglinesNode(reader.ReadSubtree(), item); diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfoProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfoProvider.cs index 8a9152507..8b59291a3 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfoProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfoProvider.cs @@ -107,17 +107,20 @@ namespace MediaBrowser.Providers.MediaInfo audio.Name = title; } - var composer = GetDictionaryValue(tags, "composer"); - - if (!string.IsNullOrWhiteSpace(composer)) + if (!audio.LockedFields.Contains(MetadataFields.Cast)) { - foreach (var person in Split(composer)) - { - var name = person.Trim(); + var composer = GetDictionaryValue(tags, "composer"); - if (!string.IsNullOrEmpty(name)) + if (!string.IsNullOrWhiteSpace(composer)) + { + foreach (var person in Split(composer)) { - audio.AddPerson(new PersonInfo { Name = name, Type = PersonType.Composer }); + var name = person.Trim(); + + if (!string.IsNullOrEmpty(name)) + { + audio.AddPerson(new PersonInfo { Name = name, Type = PersonType.Composer }); + } } } } @@ -148,12 +151,18 @@ namespace MediaBrowser.Providers.MediaInfo audio.ProductionYear = audio.PremiereDate.Value.ToLocalTime().Year; } - FetchGenres(audio, tags); + if (!audio.LockedFields.Contains(MetadataFields.Genres)) + { + FetchGenres(audio, tags); + } - // There's several values in tags may or may not be present - FetchStudios(audio, tags, "organization"); - FetchStudios(audio, tags, "ensemble"); - FetchStudios(audio, tags, "publisher"); + if (!audio.LockedFields.Contains(MetadataFields.Studios)) + { + // There's several values in tags may or may not be present + FetchStudios(audio, tags, "organization"); + FetchStudios(audio, tags, "ensemble"); + FetchStudios(audio, tags, "publisher"); + } } /// diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs index ee5df7dca..5c74c18de 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs @@ -300,14 +300,17 @@ namespace MediaBrowser.Providers.MediaInfo return; } - var genres = GetDictionaryValue(data.format.tags, "genre"); - - if (!string.IsNullOrEmpty(genres)) + if (!video.LockedFields.Contains(MetadataFields.Genres)) { - video.Genres = genres.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries) - .Where(i => !string.IsNullOrWhiteSpace(i)) - .Select(i => i.Trim()) - .ToList(); + var genres = GetDictionaryValue(data.format.tags, "genre"); + + if (!string.IsNullOrEmpty(genres)) + { + video.Genres = genres.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries) + .Where(i => !string.IsNullOrWhiteSpace(i)) + .Select(i => i.Trim()) + .ToList(); + } } var overview = GetDictionaryValue(data.format.tags, "WM/SubTitleDescription"); diff --git a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs index 278c51fc0..fee3aa4fd 100644 --- a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs +++ b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs @@ -77,7 +77,8 @@ namespace MediaBrowser.Providers.Savers "CriticRatingSummary", "GamesDbId", "BirthDate", - "DeathDate" + "DeathDate", + "LockedFields" }); var position = xml.ToString().LastIndexOf("" + item.DontFetchMeta.ToString().ToLower() + ""); + if (item.LockedFields.Count > 0) + { + builder.Append("" + string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()) + ""); + } + if (!string.IsNullOrEmpty(item.DisplayMediaType)) { builder.Append("" + SecurityElement.Escape(item.DisplayMediaType) + ""); @@ -462,7 +468,7 @@ namespace MediaBrowser.Providers.Savers { builder.Append("" + SecurityElement.Escape(stream.ScanType) + ""); } - + if (stream.Channels.HasValue) { builder.Append("" + stream.Channels.Value.ToString(UsCulture) + ""); @@ -507,7 +513,7 @@ namespace MediaBrowser.Providers.Savers } } } - + builder.Append(""); } diff --git a/MediaBrowser.Providers/TV/FanArtTVProvider.cs b/MediaBrowser.Providers/TV/FanArtTVProvider.cs index 84ac59924..e5f455a5f 100644 --- a/MediaBrowser.Providers/TV/FanArtTVProvider.cs +++ b/MediaBrowser.Providers/TV/FanArtTVProvider.cs @@ -179,28 +179,23 @@ namespace MediaBrowser.Providers.TV { cancellationToken.ThrowIfCancellationRequested(); - BaseProviderInfo data; - - if (!item.ProviderData.TryGetValue(Id, out data)) - { - data = new BaseProviderInfo(); - item.ProviderData[Id] = data; - } - var seriesId = item.GetProviderId(MetadataProviders.Tvdb); - var seriesDataPath = GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId); - var xmlPath = Path.Combine(seriesDataPath, "fanart.xml"); - - // Only download the xml if it doesn't already exist. The prescan task will take care of getting updates - if (!File.Exists(xmlPath)) + if (!string.IsNullOrEmpty(seriesId)) { - await DownloadSeriesXml(seriesDataPath, seriesId, cancellationToken).ConfigureAwait(false); - } + var seriesDataPath = GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId); + var xmlPath = Path.Combine(seriesDataPath, "fanart.xml"); - if (File.Exists(xmlPath)) - { - await FetchFromXml(item, xmlPath, cancellationToken).ConfigureAwait(false); + // Only download the xml if it doesn't already exist. The prescan task will take care of getting updates + if (!File.Exists(xmlPath)) + { + await DownloadSeriesXml(seriesDataPath, seriesId, cancellationToken).ConfigureAwait(false); + } + + if (File.Exists(xmlPath)) + { + await FetchFromXml(item, xmlPath, cancellationToken).ConfigureAwait(false); + } } SetLastRefreshed(item, DateTime.UtcNow);