diff options
9 files changed, 365 insertions, 18 deletions
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index bf96b22c1..f3c8cd45b 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -56,6 +56,7 @@ <Compile Include="MediaInfo\BaseFFProbeProvider.cs" /> <Compile Include="MediaInfo\FFProbeAudioInfoProvider.cs" /> <Compile Include="MediaInfo\FFProbeVideoInfoProvider.cs" /> + <Compile Include="Movies\BoxSetProviderFromXml.cs" /> <Compile Include="Movies\FanArtMovieProvider.cs" /> <Compile Include="Movies\FanArtMovieUpdatesPrescanTask.cs" /> <Compile Include="Movies\MovieDbImagesProvider.cs" /> @@ -78,10 +79,12 @@ <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Savers\AlbumXmlSaver.cs" /> <Compile Include="Savers\ArtistXmlSaver.cs" /> + <Compile Include="Savers\BoxSetXmlSaver.cs" /> <Compile Include="Savers\EpisodeXmlSaver.cs" /> <Compile Include="Savers\FolderXmlSaver.cs" /> <Compile Include="Savers\MovieXmlSaver.cs" /> <Compile Include="Savers\PersonXmlSaver.cs" /> + <Compile Include="Savers\SeasonXmlSaver.cs" /> <Compile Include="Savers\SeriesXmlSaver.cs" /> <Compile Include="Savers\XmlSaverHelpers.cs" /> <Compile Include="TV\EpisodeImageFromMediaLocationProvider.cs" /> @@ -94,6 +97,7 @@ <Compile Include="TV\RemoteEpisodeProvider.cs" /> <Compile Include="TV\RemoteSeasonProvider.cs" /> <Compile Include="TV\RemoteSeriesProvider.cs" /> + <Compile Include="TV\SeasonProviderFromXml.cs" /> <Compile Include="TV\SeriesProviderFromXml.cs" /> <Compile Include="TV\SeriesXmlParser.cs" /> <Compile Include="TV\TvdbPrescanTask.cs" /> diff --git a/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs b/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs new file mode 100644 index 000000000..d507f435a --- /dev/null +++ b/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs @@ -0,0 +1,102 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.Movies +{ + /// <summary> + /// Class SeriesProviderFromXml + /// </summary> + public class BoxSetProviderFromXml : BaseMetadataProvider + { + public BoxSetProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager) + : base(logManager, configurationManager) + { + } + + /// <summary> + /// Supportses the specified item. + /// </summary> + /// <param name="item">The item.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> + public override bool Supports(BaseItem item) + { + return item is BoxSet && item.LocationType == LocationType.FileSystem; + } + + /// <summary> + /// Gets the priority. + /// </summary> + /// <value>The priority.</value> + public override MetadataProviderPriority Priority + { + get { return MetadataProviderPriority.First; } + } + + /// <summary> + /// Override this to return the date that should be compared to the last refresh date + /// to determine if this provider should be re-fetched. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>DateTime.</returns> + protected override DateTime CompareDate(BaseItem item) + { + var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "collection.xml")); + return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue; + } + + /// <summary> + /// Fetches metadata and returns true or false indicating if any work that requires persistence was done + /// </summary> + /// <param name="item">The item.</param> + /// <param name="force">if set to <c>true</c> [force].</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task{System.Boolean}.</returns> + public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + { + return Fetch(item, cancellationToken); + } + + /// <summary> + /// Fetches the specified item. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> + private async Task<bool> Fetch(BaseItem item, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "collection.xml")); + + if (metadataFile != null) + { + var path = metadataFile.FullName; + + await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + new BaseItemXmlParser<BoxSet>(Logger).Fetch((BoxSet)item, path, cancellationToken); + } + finally + { + XmlParsingResourcePool.Release(); + } + + SetLastRefreshed(item, DateTime.UtcNow); + + return true; + } + + return false; + } + } +} diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 43eae7ca2..1ebae9418 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -228,6 +228,10 @@ namespace MediaBrowser.Providers.Movies /// <returns><c>true</c> if [has alt meta] [the specified item]; otherwise, <c>false</c>.</returns> internal static bool HasAltMeta(BaseItem item) { + if (item is BoxSet) + { + return item.LocationType == LocationType.FileSystem && item.ResolveArgs.ContainsMetaFileByName("collection.xml"); + } return item.LocationType == LocationType.FileSystem && item.ResolveArgs.ContainsMetaFileByName(AltMetaFileName); } diff --git a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs index 8c700c944..5cf6805ef 100644 --- a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs +++ b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.Movies return !trailer.IsLocalTrailer; } - return item is Movie || item is BoxSet || item is MusicVideo; + return item is Movie || item is MusicVideo; } /// <summary> @@ -101,28 +101,19 @@ namespace MediaBrowser.Providers.Movies } else { - var boxset = item as BoxSet; + var musicVideo = item as MusicVideo; - if (boxset != null) + if (musicVideo != null) { - new BaseItemXmlParser<BoxSet>(Logger).Fetch(boxset, path, cancellationToken); + new BaseItemXmlParser<MusicVideo>(Logger).Fetch(musicVideo, path, cancellationToken); } else { - var musicVideo = item as MusicVideo; + var trailer = item as Trailer; - if (musicVideo != null) + if (trailer != null) { - new BaseItemXmlParser<MusicVideo>(Logger).Fetch(musicVideo, path, cancellationToken); - } - else - { - var trailer = item as Trailer; - - if (trailer != null) - { - new BaseItemXmlParser<Trailer>(Logger).Fetch(trailer, path, cancellationToken); - } + new BaseItemXmlParser<Trailer>(Logger).Fetch(trailer, path, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs b/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs new file mode 100644 index 000000000..9fa38d4e5 --- /dev/null +++ b/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs @@ -0,0 +1,72 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Entities; +using System.IO; +using System.Text; +using System.Threading; + +namespace MediaBrowser.Providers.Savers +{ + public class BoxSetXmlSaver : IMetadataSaver + { + private readonly IServerConfigurationManager _config; + + public BoxSetXmlSaver(IServerConfigurationManager config) + { + _config = config; + } + + /// <summary> + /// Supportses the specified item. + /// </summary> + /// <param name="item">The item.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> + public bool Supports(BaseItem item) + { + if (item.LocationType != LocationType.FileSystem) + { + return false; + } + + if (!_config.Configuration.SaveLocalMeta) + { + return false; + } + + return item is BoxSet; + } + + /// <summary> + /// Saves the specified item. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + public void Save(BaseItem item, CancellationToken cancellationToken) + { + var builder = new StringBuilder(); + + builder.Append("<Item>"); + + XmlSaverHelpers.AddCommonNodes(item, builder); + + builder.Append("</Item>"); + + var xmlFilePath = GetSavePath(item); + + XmlSaverHelpers.Save(builder, xmlFilePath, new string[] { }); + } + + /// <summary> + /// Gets the save path. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>System.String.</returns> + public string GetSavePath(BaseItem item) + { + return Path.Combine(item.Path, "collection.xml"); + } + } +} diff --git a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs b/MediaBrowser.Providers/Savers/FolderXmlSaver.cs index 2c6117554..19193d57c 100644 --- a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/FolderXmlSaver.cs @@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Savers return false; } - return !(item is Series) && !(item is BoxSet) && !(item is MusicArtist) && !(item is MusicAlbum); + return !(item is Series) && !(item is BoxSet) && !(item is MusicArtist) && !(item is MusicAlbum) && !(item is Season); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs b/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs new file mode 100644 index 000000000..d0e19dcc5 --- /dev/null +++ b/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs @@ -0,0 +1,72 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Entities; +using System.IO; +using System.Text; +using System.Threading; + +namespace MediaBrowser.Providers.Savers +{ + public class SeasonXmlSaver : IMetadataSaver + { + private readonly IServerConfigurationManager _config; + + public SeasonXmlSaver(IServerConfigurationManager config) + { + _config = config; + } + + /// <summary> + /// Supportses the specified item. + /// </summary> + /// <param name="item">The item.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> + public bool Supports(BaseItem item) + { + if (item.LocationType != LocationType.FileSystem) + { + return false; + } + + if (!_config.Configuration.SaveLocalMeta) + { + return false; + } + + return item is Season; + } + + /// <summary> + /// Saves the specified item. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + public void Save(BaseItem item, CancellationToken cancellationToken) + { + var builder = new StringBuilder(); + + builder.Append("<Item>"); + + XmlSaverHelpers.AddCommonNodes(item, builder); + + builder.Append("</Item>"); + + var xmlFilePath = GetSavePath(item); + + XmlSaverHelpers.Save(builder, xmlFilePath, new string[] { }); + } + + /// <summary> + /// Gets the save path. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>System.String.</returns> + public string GetSavePath(BaseItem item) + { + return Path.Combine(item.Path, "season.xml"); + } + } +} diff --git a/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs b/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs new file mode 100644 index 000000000..020c80baf --- /dev/null +++ b/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs @@ -0,0 +1,102 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.TV +{ + /// <summary> + /// Class SeriesProviderFromXml + /// </summary> + public class SeasonProviderFromXml : BaseMetadataProvider + { + public SeasonProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager) + : base(logManager, configurationManager) + { + } + + /// <summary> + /// Supportses the specified item. + /// </summary> + /// <param name="item">The item.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> + public override bool Supports(BaseItem item) + { + return item is Season && item.LocationType == LocationType.FileSystem; + } + + /// <summary> + /// Gets the priority. + /// </summary> + /// <value>The priority.</value> + public override MetadataProviderPriority Priority + { + get { return MetadataProviderPriority.First; } + } + + /// <summary> + /// Override this to return the date that should be compared to the last refresh date + /// to determine if this provider should be re-fetched. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>DateTime.</returns> + protected override DateTime CompareDate(BaseItem item) + { + var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "season.xml")); + return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue; + } + + /// <summary> + /// Fetches metadata and returns true or false indicating if any work that requires persistence was done + /// </summary> + /// <param name="item">The item.</param> + /// <param name="force">if set to <c>true</c> [force].</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task{System.Boolean}.</returns> + public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + { + return Fetch(item, cancellationToken); + } + + /// <summary> + /// Fetches the specified item. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> + private async Task<bool> Fetch(BaseItem item, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "season.xml")); + + if (metadataFile != null) + { + var path = metadataFile.FullName; + + await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + new BaseItemXmlParser<Season>(Logger).Fetch((Season)item, path, cancellationToken); + } + finally + { + XmlParsingResourcePool.Release(); + } + + SetLastRefreshed(item, DateTime.UtcNow); + + return true; + } + + return false; + } + } +} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs index 2f810d2a1..fc3906ebb 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs @@ -29,7 +29,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies return null; } - if (filename.IndexOf("[boxset]", StringComparison.OrdinalIgnoreCase) != -1) + if (filename.IndexOf("[boxset]", StringComparison.OrdinalIgnoreCase) != -1 || args.ContainsFileSystemEntryByName("collection.xml")) { return new BoxSet(); } |
