diff options
99 files changed, 1186 insertions, 769 deletions
diff --git a/MediaBrowser.Api/LibraryService.cs b/MediaBrowser.Api/LibraryService.cs index 51eef225e..48037e801 100644 --- a/MediaBrowser.Api/LibraryService.cs +++ b/MediaBrowser.Api/LibraryService.cs @@ -370,44 +370,6 @@ namespace MediaBrowser.Api UniqueTypes = items.Select(i => i.GetClientTypeName()).Distinct().ToList() }; - var people = items.SelectMany(i => i.People) - .Select(i => i.Name) - .Distinct(StringComparer.OrdinalIgnoreCase) - .Select(i => - { - try - { - return _libraryManager.GetPerson(i); - } - catch - { - return null; - } - }) - .Where(i => i != null) - .ToList(); - - people = request.UserId.HasValue ? FilterItems(people, request, request.UserId.Value).ToList() : people; - counts.PersonCount = people.Count; - - var artists = _libraryManager.GetAllArtists(items) - .Select(i => - { - try - { - return _libraryManager.GetArtist(i); - } - catch - { - return null; - } - }) - .Where(i => i != null) - .ToList(); - - artists = request.UserId.HasValue ? FilterItems(artists, request, request.UserId.Value).ToList() : artists; - counts.ArtistCount = artists.Count; - return ToOptimizedResult(counts); } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 9ad0703ae..e34f0888d 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -7,6 +7,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaInfo; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -59,7 +60,9 @@ namespace MediaBrowser.Api.Playback protected IDtoService DtoService { get; private set; } protected IFileSystem FileSystem { get; private set; } - + + protected IItemRepository ItemRepository { get; private set; } + /// <summary> /// Initializes a new instance of the <see cref="BaseStreamingService" /> class. /// </summary> @@ -68,8 +71,9 @@ namespace MediaBrowser.Api.Playback /// <param name="libraryManager">The library manager.</param> /// <param name="isoManager">The iso manager.</param> /// <param name="mediaEncoder">The media encoder.</param> - protected BaseStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem) + protected BaseStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) { + ItemRepository = itemRepository; FileSystem = fileSystem; DtoService = dtoService; ApplicationPaths = appPaths; @@ -803,6 +807,12 @@ namespace MediaBrowser.Api.Playback var videoRequest = request as VideoStreamRequest; + var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery + { + ItemId = item.Id + + }).ToList(); + if (videoRequest != null) { if (!videoRequest.VideoCodec.HasValue) @@ -810,13 +820,13 @@ namespace MediaBrowser.Api.Playback videoRequest.VideoCodec = InferVideoCodec(url); } - state.VideoStream = GetMediaStream(media.MediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video); - state.SubtitleStream = GetMediaStream(media.MediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false); - state.AudioStream = GetMediaStream(media.MediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio); + state.VideoStream = GetMediaStream(mediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video); + state.SubtitleStream = GetMediaStream(mediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false); + state.AudioStream = GetMediaStream(mediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio); } else { - state.AudioStream = GetMediaStream(media.MediaStreams, null, MediaStreamType.Audio, true); + state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true); } return state; diff --git a/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs b/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs index 6636db05d..073cd1b7f 100644 --- a/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; using ServiceStack.ServiceHost; @@ -25,16 +26,8 @@ namespace MediaBrowser.Api.Playback.Hls /// </summary> public class AudioHlsService : BaseHlsService { - /// <summary> - /// Initializes a new instance of the <see cref="AudioHlsService" /> class. - /// </summary> - /// <param name="appPaths">The app paths.</param> - /// <param name="userManager">The user manager.</param> - /// <param name="libraryManager">The library manager.</param> - /// <param name="isoManager">The iso manager.</param> - /// <param name="mediaEncoder">The media encoder.</param> - public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem) - : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem) + public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) + : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository) { } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 3e96cf2f8..1e5e8b82d 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; using System; @@ -21,6 +22,11 @@ namespace MediaBrowser.Api.Playback.Hls /// </summary> public abstract class BaseHlsService : BaseStreamingService { + protected BaseHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) + : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository) + { + } + protected override string GetOutputFilePath(StreamState state) { var folder = ApplicationPaths.EncodedMediaCachePath; @@ -31,19 +37,6 @@ namespace MediaBrowser.Api.Playback.Hls } /// <summary> - /// Initializes a new instance of the <see cref="BaseStreamingService" /> class. - /// </summary> - /// <param name="appPaths">The app paths.</param> - /// <param name="userManager">The user manager.</param> - /// <param name="libraryManager">The library manager.</param> - /// <param name="isoManager">The iso manager.</param> - /// <param name="mediaEncoder">The media encoder.</param> - protected BaseHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem) - : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem) - { - } - - /// <summary> /// Gets the audio arguments. /// </summary> /// <param name="state">The state.</param> @@ -260,7 +253,7 @@ namespace MediaBrowser.Api.Playback.Hls var itsOffsetMs = hlsVideoRequest == null ? 0 - : ((GetHlsVideoStream) state.VideoRequest).TimeStampOffsetMs; + : ((GetHlsVideoStream)state.VideoRequest).TimeStampOffsetMs; var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds); diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index dfd18ab15..b194a47fe 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.IO; using ServiceStack.ServiceHost; using System; @@ -31,17 +32,8 @@ namespace MediaBrowser.Api.Playback.Hls /// </summary> public class VideoHlsService : BaseHlsService { - /// <summary> - /// Initializes a new instance of the <see cref="BaseStreamingService" /> class. - /// </summary> - /// <param name="appPaths">The app paths.</param> - /// <param name="userManager">The user manager.</param> - /// <param name="libraryManager">The library manager.</param> - /// <param name="isoManager">The iso manager.</param> - /// <param name="mediaEncoder">The media encoder.</param> - /// <param name="dtoService">The dto service.</param> - public VideoHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem) - : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem) + public VideoHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) + : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository) { } @@ -95,13 +87,13 @@ namespace MediaBrowser.Api.Playback.Hls { volParam = ",volume=2.000000"; } - + if (state.Request.AudioSampleRate.HasValue) { - audioSampleRate= state.Request.AudioSampleRate.Value + ":"; + audioSampleRate = state.Request.AudioSampleRate.Value + ":"; } - args += string.Format(" -af \"adelay=1,aresample={0}async=1000{1}\"",audioSampleRate, volParam); + args += string.Format(" -af \"adelay=1,aresample={0}async=1000{1}\"", audioSampleRate, volParam); return args; } @@ -130,7 +122,7 @@ namespace MediaBrowser.Api.Playback.Hls var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsExternal && (state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 || state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1); - + var args = "-codec:v:0 " + codec + " -preset superfast" + keyFrameArg; var bitrate = GetVideoBitrateParam(state); @@ -139,7 +131,7 @@ namespace MediaBrowser.Api.Playback.Hls { args += string.Format(" -b:v {0} -maxrate ({0}*.85) -bufsize {0}", bitrate.Value.ToString(UsCulture)); } - + // Add resolution params, if specified if (!hasGraphicalSubs) { @@ -171,7 +163,7 @@ namespace MediaBrowser.Api.Playback.Hls { args += GetInternalGraphicalSubtitleParam(state, codec); } - + return args; } diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 1f0853e08..2447302f5 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using System; using System.Collections.Generic; using System.IO; using System.Net.Http; @@ -25,13 +24,11 @@ namespace MediaBrowser.Api.Playback.Progressive /// </summary> public abstract class BaseProgressiveStreamingService : BaseStreamingService { - protected readonly IItemRepository ItemRepository; protected readonly IImageProcessor ImageProcessor; protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepository, IDtoService dtoService, IImageProcessor imageProcessor, IFileSystem fileSystem) : - base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem) + base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository) { - ItemRepository = itemRepository; ImageProcessor = imageProcessor; } diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 7cb624af8..380e09463 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -226,7 +226,7 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "HasTvdbId", Description = "Optional filter by items that have a tvdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? HasTvdbId { get; set; } - + [ApiMember(Name = "IsYearMismatched", Description = "Optional filter by items that are potentially misidentified.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? IsYearMismatched { get; set; } } @@ -984,15 +984,9 @@ namespace MediaBrowser.Api.UserLibrary if (request.HasSubtitles.HasValue) { - items = items.OfType<Video>().Where(i => - { - if (request.HasSubtitles.Value) - { - return i.MediaStreams != null && i.MediaStreams.Any(m => m.Type == MediaStreamType.Subtitle); - } + var val = request.HasSubtitles.Value; - return i.MediaStreams == null || i.MediaStreams.All(m => m.Type != MediaStreamType.Subtitle); - }); + items = items.OfType<Video>().Where(i => val == i.HasSubtitles); } if (request.HasParentalRating.HasValue) diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 2a7aa4fea..63c907c1f 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Model.Entities; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; @@ -13,7 +12,6 @@ namespace MediaBrowser.Controller.Entities.Audio { public Audio() { - MediaStreams = new List<MediaStream>(); Artists = new List<string>(); } @@ -22,13 +20,13 @@ namespace MediaBrowser.Controller.Entities.Audio /// </summary> /// <value>The language.</value> public string Language { get; set; } - + /// <summary> - /// Gets or sets the media streams. + /// Gets or sets a value indicating whether this instance has embedded image. /// </summary> - /// <value>The media streams.</value> - public List<MediaStream> MediaStreams { get; set; } - + /// <value><c>true</c> if this instance has embedded image; otherwise, <c>false</c>.</value> + public bool HasEmbeddedImage { get; set; } + /// <summary> /// Override this to true if class should be grouped under a container in indicies /// The container class should be defined via IndexContainer diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 2be4c7708..541887598 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -154,6 +154,8 @@ namespace MediaBrowser.Controller.Entities /// <value>The date modified.</value> public DateTime DateModified { get; set; } + public DateTime DateLastSaved { get; set; } + /// <summary> /// The logger /// </summary> @@ -200,29 +202,6 @@ namespace MediaBrowser.Controller.Entities } /// <summary> - /// The _provider data - /// </summary> - private Dictionary<Guid, BaseProviderInfo> _providerData; - /// <summary> - /// Holds persistent data for providers like last refresh date. - /// Providers can use this to determine if they need to refresh. - /// The BaseProviderInfo class can be extended to hold anything a provider may need. - /// Keyed by a unique provider ID. - /// </summary> - /// <value>The provider data.</value> - public Dictionary<Guid, BaseProviderInfo> ProviderData - { - get - { - return _providerData ?? (_providerData = new Dictionary<Guid, BaseProviderInfo>()); - } - set - { - _providerData = value; - } - } - - /// <summary> /// Gets the type of the media. /// </summary> /// <value>The type of the media.</value> @@ -827,7 +806,7 @@ namespace MediaBrowser.Controller.Entities /// <returns>true if a provider reports we changed</returns> public virtual async Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true) { - if (resetResolveArgs || ResolveArgs == null) + if (resetResolveArgs) { // Reload this ResetResolveArgs(); diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs index 20df731a7..87b90b824 100644 --- a/MediaBrowser.Controller/Entities/Book.cs +++ b/MediaBrowser.Controller/Entities/Book.cs @@ -1,7 +1,8 @@ - +using System.Collections.Generic; + namespace MediaBrowser.Controller.Entities { - public class Book : BaseItem + public class Book : BaseItem, IHasTags { public override string MediaType { @@ -10,6 +11,11 @@ namespace MediaBrowser.Controller.Entities return Model.Entities.MediaType.Book; } } + /// <summary> + /// Gets or sets the tags. + /// </summary> + /// <value>The tags.</value> + public List<string> Tags { get; set; } public string SeriesName { get; set; } @@ -31,5 +37,10 @@ namespace MediaBrowser.Controller.Entities return !IsInMixedFolder; } } + + public Book() + { + Tags = new List<string>(); + } } } diff --git a/MediaBrowser.Controller/Entities/IHasMediaStreams.cs b/MediaBrowser.Controller/Entities/IHasMediaStreams.cs new file mode 100644 index 000000000..b700ef628 --- /dev/null +++ b/MediaBrowser.Controller/Entities/IHasMediaStreams.cs @@ -0,0 +1,10 @@ + +namespace MediaBrowser.Controller.Entities +{ + /// <summary> + /// This is essentially a marker interface + /// </summary> + public interface IHasMediaStreams + { + } +} diff --git a/MediaBrowser.Controller/Entities/IHasScreenshots.cs b/MediaBrowser.Controller/Entities/IHasScreenshots.cs index 341d6403f..2276c707a 100644 --- a/MediaBrowser.Controller/Entities/IHasScreenshots.cs +++ b/MediaBrowser.Controller/Entities/IHasScreenshots.cs @@ -12,5 +12,10 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value>The screenshot image paths.</value> List<string> ScreenshotImagePaths { get; set; } + + /// <summary> + /// Validates the screenshots. + /// </summary> + void ValidateScreenshots(); } } diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 9b02571b0..425e418ed 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -22,12 +22,29 @@ namespace MediaBrowser.Controller.Entities public Video() { - MediaStreams = new List<MediaStream>(); PlayableStreamFileNames = new List<string>(); AdditionalPartIds = new List<Guid>(); } /// <summary> + /// Gets or sets a value indicating whether this instance has subtitles. + /// </summary> + /// <value><c>true</c> if this instance has subtitles; otherwise, <c>false</c>.</value> + public bool HasSubtitles { get; set; } + + /// <summary> + /// Gets or sets the video bit rate. + /// </summary> + /// <value>The video bit rate.</value> + public int? VideoBitRate { get; set; } + + /// <summary> + /// Gets or sets the default index of the video stream. + /// </summary> + /// <value>The default index of the video stream.</value> + public int? DefaultVideoStreamIndex { get; set; } + + /// <summary> /// Gets or sets the type of the video. /// </summary> /// <value>The type of the video.</value> @@ -46,12 +63,6 @@ namespace MediaBrowser.Controller.Entities public Video3DFormat? Video3DFormat { get; set; } /// <summary> - /// Gets or sets the media streams. - /// </summary> - /// <value>The media streams.</value> - public List<MediaStream> MediaStreams { get; set; } - - /// <summary> /// If the video is a folder-rip, this will hold the file list for the largest playlist /// </summary> public List<string> PlayableStreamFileNames { get; set; } @@ -70,7 +81,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value>The aspect ratio.</value> public string AspectRatio { get; set; } - + /// <summary> /// Should be overridden to return the proper folder where metadata lives /// </summary> @@ -123,16 +134,6 @@ namespace MediaBrowser.Controller.Entities } /// <summary> - /// The default video stream for this video. Use this to determine media info for this item. - /// </summary> - /// <value>The default video stream.</value> - [IgnoreDataMember] - public MediaStream DefaultVideoStream - { - get { return MediaStreams != null ? MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video) : null; } - } - - /// <summary> /// Gets a value indicating whether [is3 D]. /// </summary> /// <value><c>true</c> if [is3 D]; otherwise, <c>false</c>.</value> diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 03aa1413b..21c9e39f1 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -93,6 +93,7 @@ <Compile Include="Entities\IHasBudget.cs" /> <Compile Include="Entities\IHasCriticRating.cs" /> <Compile Include="Entities\IHasLanguage.cs" /> + <Compile Include="Entities\IHasMediaStreams.cs" /> <Compile Include="Entities\IHasProductionLocations.cs" /> <Compile Include="Entities\IHasScreenshots.cs" /> <Compile Include="Entities\IHasSoundtracks.cs" /> @@ -124,6 +125,7 @@ <Compile Include="Localization\ILocalizationManager.cs" /> <Compile Include="Notifications\INotificationsRepository.cs" /> <Compile Include="Notifications\NotificationUpdateEventArgs.cs" /> + <Compile Include="Persistence\MediaStreamQuery.cs" /> <Compile Include="Providers\IDynamicInfoProvider.cs" /> <Compile Include="Providers\IImageProvider.cs" /> <Compile Include="Providers\NameParser.cs" /> diff --git a/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs b/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs index fd1b12c2f..e53acfc02 100644 --- a/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs +++ b/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs @@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.MediaInfo return Path.Combine(_appPaths.CachePath, "subtitles"); } } - + /// <summary> /// The first chapter ticks /// </summary> @@ -112,7 +112,7 @@ namespace MediaBrowser.Controller.MediaInfo public async Task<bool> PopulateChapterImages(Video video, List<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken) { // Can't extract images if there are no video streams - if (video.MediaStreams == null || video.MediaStreams.All(m => m.Type != MediaStreamType.Video)) + if (!video.DefaultVideoStreamIndex.HasValue) { return true; } @@ -164,7 +164,7 @@ namespace MediaBrowser.Controller.MediaInfo var parentPath = Path.GetDirectoryName(path); Directory.CreateDirectory(parentPath); - + await _encoder.ExtractImage(inputPath, type, video.Video3DFormat, time, path, cancellationToken).ConfigureAwait(false); chapter.ImagePath = path; changesMade = true; @@ -203,7 +203,17 @@ namespace MediaBrowser.Controller.MediaInfo { var ticksParam = offset.HasValue ? "_" + offset.Value.Ticks : ""; - var stream = input.MediaStreams[subtitleStreamIndex]; + var stream = _itemRepo.GetMediaStreams(new MediaStreamQuery + { + ItemId = input.Id, + Index = subtitleStreamIndex + + }).FirstOrDefault(); + + if (stream == null) + { + return null; + } if (stream.IsExternal) { diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index e04f25605..3affe48e7 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; @@ -95,6 +96,38 @@ namespace MediaBrowser.Controller.Persistence /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> Task SaveChildren(Guid parentId, IEnumerable<Guid> children, CancellationToken cancellationToken); + + /// <summary> + /// Gets the media streams. + /// </summary> + /// <param name="query">The query.</param> + /// <returns>IEnumerable{MediaStream}.</returns> + IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query); + + /// <summary> + /// Saves the media streams. + /// </summary> + /// <param name="id">The identifier.</param> + /// <param name="streams">The streams.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken); + + /// <summary> + /// Gets the provider history. + /// </summary> + /// <param name="itemId">The item identifier.</param> + /// <returns>IEnumerable{BaseProviderInfo}.</returns> + IEnumerable<BaseProviderInfo> GetProviderHistory(Guid itemId); + + /// <summary> + /// Saves the provider history. + /// </summary> + /// <param name="id">The identifier.</param> + /// <param name="history">The history.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + Task SaveProviderHistory(Guid id, IEnumerable<BaseProviderInfo> history, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Persistence/MediaStreamQuery.cs b/MediaBrowser.Controller/Persistence/MediaStreamQuery.cs new file mode 100644 index 000000000..10985f57d --- /dev/null +++ b/MediaBrowser.Controller/Persistence/MediaStreamQuery.cs @@ -0,0 +1,26 @@ +using MediaBrowser.Model.Entities; +using System; + +namespace MediaBrowser.Controller.Persistence +{ + public class MediaStreamQuery + { + /// <summary> + /// Gets or sets the type. + /// </summary> + /// <value>The type.</value> + public MediaStreamType? Type { get; set; } + + /// <summary> + /// Gets or sets the index. + /// </summary> + /// <value>The index.</value> + public int? Index { get; set; } + + /// <summary> + /// Gets or sets the item identifier. + /// </summary> + /// <value>The item identifier.</value> + public Guid ItemId { get; set; } + } +} diff --git a/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs b/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs index 07bb7d5b2..40afe0b54 100644 --- a/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Controller.Providers /// <summary> /// The _id /// </summary> - protected readonly Guid Id; + public readonly Guid Id; /// <summary> /// The true task result @@ -132,41 +132,33 @@ namespace MediaBrowser.Controller.Providers /// <param name="item">The item.</param> /// <param name="value">The value.</param> /// <param name="providerVersion">The provider version.</param> + /// <param name="providerInfo">The provider information.</param> /// <param name="status">The status.</param> /// <exception cref="System.ArgumentNullException">item</exception> public virtual void SetLastRefreshed(BaseItem item, DateTime value, string providerVersion, - ProviderRefreshStatus status = ProviderRefreshStatus.Success) + BaseProviderInfo providerInfo, ProviderRefreshStatus status = ProviderRefreshStatus.Success) { if (item == null) { throw new ArgumentNullException("item"); } - BaseProviderInfo data; - - if (!item.ProviderData.TryGetValue(Id, out data)) - { - data = new BaseProviderInfo(); - } - - data.LastRefreshed = value; - data.LastRefreshStatus = status; - data.ProviderVersion = providerVersion; + providerInfo.LastRefreshed = value; + providerInfo.LastRefreshStatus = status; + providerInfo.ProviderVersion = providerVersion; // Save the file system stamp for future comparisons if (RefreshOnFileSystemStampChange && item.LocationType == LocationType.FileSystem) { try { - data.FileStamp = GetCurrentFileSystemStamp(item); + providerInfo.FileStamp = GetCurrentFileSystemStamp(item); } catch (IOException ex) { Logger.ErrorException("Error getting file stamp for {0}", ex, item.Path); } } - - item.ProviderData[Id] = data; } /// <summary> @@ -174,11 +166,12 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <param name="item">The item.</param> /// <param name="value">The value.</param> + /// <param name="providerInfo">The provider information.</param> /// <param name="status">The status.</param> public void SetLastRefreshed(BaseItem item, DateTime value, - ProviderRefreshStatus status = ProviderRefreshStatus.Success) + BaseProviderInfo providerInfo, ProviderRefreshStatus status = ProviderRefreshStatus.Success) { - SetLastRefreshed(item, value, ProviderVersion, status); + SetLastRefreshed(item, value, ProviderVersion, providerInfo, status); } /// <summary> @@ -189,20 +182,13 @@ namespace MediaBrowser.Controller.Providers /// <param name="item">The item.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> /// <exception cref="System.ArgumentNullException"></exception> - public bool NeedsRefresh(BaseItem item) + public bool NeedsRefresh(BaseItem item, BaseProviderInfo data) { if (item == null) { throw new ArgumentNullException(); } - BaseProviderInfo data; - - if (!item.ProviderData.TryGetValue(Id, out data)) - { - data = new BaseProviderInfo(); - } - return NeedsRefreshInternal(item, data); } @@ -299,10 +285,11 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <param name="item">The item.</param> /// <param name="force">if set to <c>true</c> [force].</param> + /// <param name="providerInfo">The provider information.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{System.Boolean}.</returns> /// <exception cref="System.ArgumentNullException"></exception> - public abstract Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken); + public abstract Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken); /// <summary> /// Gets the priority. diff --git a/MediaBrowser.Controller/Providers/BaseProviderInfo.cs b/MediaBrowser.Controller/Providers/BaseProviderInfo.cs index 243ce32af..829dd34c8 100644 --- a/MediaBrowser.Controller/Providers/BaseProviderInfo.cs +++ b/MediaBrowser.Controller/Providers/BaseProviderInfo.cs @@ -7,6 +7,7 @@ namespace MediaBrowser.Controller.Providers /// </summary> public class BaseProviderInfo { + public Guid ProviderId { get; set; } /// <summary> /// Gets or sets the last refreshed. /// </summary> diff --git a/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs b/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs index b39205b5d..7d9739448 100644 --- a/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs +++ b/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs @@ -1,6 +1,5 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using System; using System.Collections.Generic; @@ -46,6 +45,7 @@ namespace MediaBrowser.Controller.Resolvers ".3gp", ".webm", ".mts", + ".m2v", ".rec" }; diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 67888aa46..f6e2725a6 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -143,9 +143,6 @@ <Compile Include="..\MediaBrowser.Model\Entities\DisplayPreferences.cs"> <Link>Entities\DisplayPreferences.cs</Link> </Compile> - <Compile Include="..\MediaBrowser.Model\Entities\IHasMediaStreams.cs"> - <Link>Entities\IHasMediaStreams.cs</Link> - </Compile> <Compile Include="..\MediaBrowser.Model\Entities\IHasProviderIds.cs"> <Link>Entities\IHasProviderIds.cs</Link> </Compile> diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index cfe4a5462..efafc7f62 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -130,9 +130,6 @@ <Compile Include="..\MediaBrowser.Model\Entities\DisplayPreferences.cs"> <Link>Entities\DisplayPreferences.cs</Link> </Compile> - <Compile Include="..\MediaBrowser.Model\Entities\IHasMediaStreams.cs"> - <Link>Entities\IHasMediaStreams.cs</Link> - </Compile> <Compile Include="..\MediaBrowser.Model\Entities\IHasProviderIds.cs"> <Link>Entities\IHasProviderIds.cs</Link> </Compile> diff --git a/MediaBrowser.Model/Dto/ItemCounts.cs b/MediaBrowser.Model/Dto/ItemCounts.cs index 34fe6ca64..34e2a1c3c 100644 --- a/MediaBrowser.Model/Dto/ItemCounts.cs +++ b/MediaBrowser.Model/Dto/ItemCounts.cs @@ -68,9 +68,6 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The unique types.</value> public List<string> UniqueTypes { get; set; } - - public int PersonCount { get; set; } - public int ArtistCount { get; set; } public ItemCounts() { diff --git a/MediaBrowser.Model/Entities/IHasMediaStreams.cs b/MediaBrowser.Model/Entities/IHasMediaStreams.cs deleted file mode 100644 index a00914146..000000000 --- a/MediaBrowser.Model/Entities/IHasMediaStreams.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Model.Entities -{ - /// <summary> - /// This is essentially a marker interface - /// </summary> - public interface IHasMediaStreams - { - /// <summary> - /// Gets or sets the media streams. - /// </summary> - /// <value>The media streams.</value> - List<MediaStream> MediaStreams { get; set; } - /// <summary> - /// Gets or sets the path. - /// </summary> - /// <value>The path.</value> - string Path { get; set; } - /// <summary> - /// Gets or sets the primary image path. - /// </summary> - /// <value>The primary image path.</value> - string PrimaryImagePath { get; } - } -} diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 5e85369b9..133631649 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -19,10 +19,10 @@ namespace MediaBrowser.Model.Entities public string Language { get; set; } /// <summary> - /// Gets or sets the type of the scan. + /// Gets or sets a value indicating whether this instance is interlaced. /// </summary> - /// <value>The type of the scan.</value> - public string ScanType { get; set; } + /// <value><c>true</c> if this instance is interlaced; otherwise, <c>false</c>.</value> + public bool IsInterlaced { get; set; } /// <summary> /// Gets or sets the channel layout. diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 103e583ae..5175bee91 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -125,7 +125,6 @@ <Compile Include="Entities\ParentalRating.cs" /> <Compile Include="Dto\StreamOptions.cs" /> <Compile Include="Entities\VirtualFolderInfo.cs" /> - <Compile Include="Entities\IHasMediaStreams.cs" /> <Compile Include="Extensions\ModelExtensions.cs" /> <Compile Include="IO\IZipClient.cs" /> <Compile Include="Logging\ILogger.cs" /> diff --git a/MediaBrowser.Mono.sln b/MediaBrowser.Mono.sln index b7961816d..397763489 100644 --- a/MediaBrowser.Mono.sln +++ b/MediaBrowser.Mono.sln @@ -23,42 +23,61 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 Release|x86 = Release|x86 + Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {175A9388-F352-4586-A6B4-070DED62B644}.Debug|x86.ActiveCfg = Debug|x86 {175A9388-F352-4586-A6B4-070DED62B644}.Debug|x86.Build.0 = Debug|x86 + {175A9388-F352-4586-A6B4-070DED62B644}.Release|Any CPU.ActiveCfg = Release|Any CPU + {175A9388-F352-4586-A6B4-070DED62B644}.Release|Any CPU.Build.0 = Release|Any CPU {175A9388-F352-4586-A6B4-070DED62B644}.Release|x86.ActiveCfg = Release|x86 {175A9388-F352-4586-A6B4-070DED62B644}.Release|x86.Build.0 = Release|x86 {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.ActiveCfg = Debug|x86 {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.Build.0 = Debug|x86 - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.ActiveCfg = Release|x86 - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.Build.0 = Release|x86 + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.Build.0 = Release|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.ActiveCfg = Release|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.Build.0 = Release|Any CPU {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.ActiveCfg = Debug|Any CPU {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.Build.0 = Debug|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.Build.0 = Release|Any CPU {2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.ActiveCfg = Release|Any CPU {2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.Build.0 = Release|Any CPU {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|x86.ActiveCfg = Debug|Any CPU {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|x86.Build.0 = Debug|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.ActiveCfg = Release|Any CPU {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.Build.0 = Release|Any CPU {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.ActiveCfg = Debug|Any CPU {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.Build.0 = Debug|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.Build.0 = Release|Any CPU {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x86.ActiveCfg = Release|Any CPU {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x86.Build.0 = Release|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x86.ActiveCfg = Debug|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x86.Build.0 = Debug|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.Build.0 = Release|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.ActiveCfg = Release|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.Build.0 = Release|Any CPU {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x86.ActiveCfg = Debug|Any CPU {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x86.Build.0 = Debug|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.Build.0 = Release|Any CPU {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.ActiveCfg = Release|Any CPU {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.Build.0 = Release|Any CPU {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.ActiveCfg = Debug|Any CPU {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.Build.0 = Debug|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.Build.0 = Release|Any CPU {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x86.ActiveCfg = Release|Any CPU {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x86.Build.0 = Release|Any CPU {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|x86.ActiveCfg = Debug|Any CPU {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|x86.Build.0 = Debug|Any CPU + {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Any CPU.Build.0 = Release|Any CPU {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|x86.ActiveCfg = Release|Any CPU {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection diff --git a/MediaBrowser.Mono.userprefs b/MediaBrowser.Mono.userprefs index 42e34287b..51ba9d804 100644 --- a/MediaBrowser.Mono.userprefs +++ b/MediaBrowser.Mono.userprefs @@ -1,17 +1,13 @@ <Properties> - <MonoDevelop.Ide.Workspace ActiveConfiguration="Release|x86" /> - <MonoDevelop.Ide.Workbench ActiveDocument="MediaBrowser.ServerApplication\EntryPoints\StartupWizard.cs"> + <MonoDevelop.Ide.Workspace ActiveConfiguration="Release" /> + <MonoDevelop.Ide.Workbench ActiveDocument="MediaBrowser.Server.Mono\app.config"> <Files> - <File FileName="MediaBrowser.Server.Mono\Program.cs" Line="13" Column="1" /> - <File FileName="MediaBrowser.ServerApplication\EntryPoints\StartupWizard.cs" Line="32" Column="23" /> + <File FileName="MediaBrowser.Server.Mono\app.config" Line="3" Column="19" /> </Files> <Pads> <Pad Id="ProjectPad"> - <State expanded="True"> - <Node name="MediaBrowser.Server.Mono" expanded="True" selected="True"> - <Node name="References" expanded="True" /> - <Node name="EntryPoints" expanded="True" /> - </Node> + <State expanded="True" selected="True"> + <Node name="MediaBrowser.Server.Implementations" expanded="True" /> </State> </Pad> <Pad Id="ClassPad"> @@ -24,8 +20,6 @@ </MonoDevelop.Ide.Workbench> <MonoDevelop.Ide.DebuggingService.Breakpoints> <BreakpointStore> - <Breakpoint file="D:\Development\MediaBrowser\MediaBrowser.Server.Mono\Native\NativeApp.cs" line="23" column="1" /> - <Breakpoint file="D:\Development\MediaBrowser\MediaBrowser.Server.Mono\Native\NativeApp.cs" line="15" column="1" /> <Breakpoint file="D:\Development\MediaBrowser\MediaBrowser.Common.Implementations\HttpClientManager\HttpClientManager.cs" line="477" column="17" /> </BreakpointStore> </MonoDevelop.Ide.DebuggingService.Breakpoints> diff --git a/MediaBrowser.Providers/FolderProviderFromXml.cs b/MediaBrowser.Providers/FolderProviderFromXml.cs index 8459fceef..31e4bc8bc 100644 --- a/MediaBrowser.Providers/FolderProviderFromXml.cs +++ b/MediaBrowser.Providers/FolderProviderFromXml.cs @@ -1,7 +1,6 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; @@ -17,14 +16,12 @@ namespace MediaBrowser.Providers /// </summary> public class FolderProviderFromXml : BaseMetadataProvider { - public static FolderProviderFromXml Current; private readonly IFileSystem _fileSystem; public FolderProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -56,7 +53,7 @@ namespace MediaBrowser.Providers return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -64,20 +61,10 @@ namespace MediaBrowser.Providers /// </summary> /// <param name="item">The item.</param> /// <param name="force">if set to <c>true</c> [force].</param> + /// <param name="providerInfo">The provider information.</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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -97,12 +84,10 @@ namespace MediaBrowser.Providers { XmlParsingResourcePool.Release(); } - - SetLastRefreshed(item, DateTime.UtcNow); - return true; } - return false; + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); + return true; } } } diff --git a/MediaBrowser.Providers/Games/GameProviderFromXml.cs b/MediaBrowser.Providers/Games/GameProviderFromXml.cs index 724e3f5fa..ab1f96a8e 100644 --- a/MediaBrowser.Providers/Games/GameProviderFromXml.cs +++ b/MediaBrowser.Providers/Games/GameProviderFromXml.cs @@ -1,7 +1,6 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Savers; @@ -48,7 +47,7 @@ namespace MediaBrowser.Providers.Games return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -58,19 +57,9 @@ namespace MediaBrowser.Providers.Games /// <param name="force"></param> /// <param name="cancellationToken"></param> /// <returns></returns> - public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) - { - return Fetch((Game)item, cancellationToken); - } - - /// <summary> - /// - /// </summary> - /// <param name="game"></param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - private async Task<bool> Fetch(Game game, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { + var game = (Game)item; cancellationToken.ThrowIfCancellationRequested(); var metaFile = GameXmlSaver.GetGameSavePath(game); @@ -89,7 +78,7 @@ namespace MediaBrowser.Providers.Games } } - SetLastRefreshed(game, DateTime.UtcNow); + SetLastRefreshed(game, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs b/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs index 0c9d55a09..58143ce3d 100644 --- a/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs +++ b/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs @@ -1,7 +1,6 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; @@ -14,14 +13,12 @@ namespace MediaBrowser.Providers.Games { public class GameSystemProviderFromXml : BaseMetadataProvider { - internal static GameSystemProviderFromXml Current { get; private set; } private readonly IFileSystem _fileSystem; public GameSystemProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -53,7 +50,7 @@ namespace MediaBrowser.Providers.Games return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -63,18 +60,7 @@ namespace MediaBrowser.Providers.Games /// <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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -95,7 +81,7 @@ namespace MediaBrowser.Providers.Games XmlParsingResourcePool.Release(); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs b/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs index 70d9e788d..08e62afc5 100644 --- a/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs +++ b/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.Providers /// <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) + public override Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -108,7 +108,12 @@ namespace MediaBrowser.Providers // Make sure current backdrop paths still exist item.ValidateBackdrops(); - item.ValidateScreenshots(); + + var hasScreenshots = item as IHasScreenshots; + if (hasScreenshots != null) + { + hasScreenshots.ValidateScreenshots(); + } cancellationToken.ThrowIfCancellationRequested(); @@ -116,7 +121,7 @@ namespace MediaBrowser.Providers PopulateBaseItemImages(item, args); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return TrueTaskResult; } diff --git a/MediaBrowser.Providers/LiveTv/ChannelProviderFromXml.cs b/MediaBrowser.Providers/LiveTv/ChannelProviderFromXml.cs index b166750b5..b0bc1b875 100644 --- a/MediaBrowser.Providers/LiveTv/ChannelProviderFromXml.cs +++ b/MediaBrowser.Providers/LiveTv/ChannelProviderFromXml.cs @@ -13,14 +13,12 @@ namespace MediaBrowser.Providers.LiveTv { class ChannelProviderFromXml : BaseMetadataProvider { - internal static ChannelProviderFromXml Current { get; private set; } private readonly IFileSystem _fileSystem; public ChannelProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -52,7 +50,7 @@ namespace MediaBrowser.Providers.LiveTv return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -62,18 +60,7 @@ namespace MediaBrowser.Providers.LiveTv /// <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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -94,7 +81,7 @@ namespace MediaBrowser.Providers.LiveTv XmlParsingResourcePool.Release(); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index 683dd4231..264b24b87 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -121,13 +121,13 @@ namespace MediaBrowser.Providers.MediaInfo /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { item.ValidateImages(); var audio = (Audio)item; - if (string.IsNullOrEmpty(audio.PrimaryImagePath) && audio.MediaStreams.Any(s => s.Type == MediaStreamType.Video)) + if (string.IsNullOrEmpty(audio.PrimaryImagePath) && audio.HasEmbeddedImage) { try { @@ -139,7 +139,7 @@ namespace MediaBrowser.Providers.MediaInfo } } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfoProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfoProvider.cs index 3594c53c5..673abea57 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfoProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfoProvider.cs @@ -3,6 +3,8 @@ using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; @@ -19,12 +21,15 @@ namespace MediaBrowser.Providers.MediaInfo /// </summary> public class FFProbeAudioInfoProvider : BaseFFProbeProvider<Audio> { - public FFProbeAudioInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder, IJsonSerializer jsonSerializer) + private readonly IItemRepository _itemRepo; + + public FFProbeAudioInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder, IJsonSerializer jsonSerializer, IItemRepository itemRepo) : base(logManager, configurationManager, mediaEncoder, jsonSerializer) { + _itemRepo = itemRepo; } - public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var myItem = (Audio)item; @@ -38,9 +43,9 @@ namespace MediaBrowser.Providers.MediaInfo cancellationToken.ThrowIfCancellationRequested(); - Fetch(myItem, cancellationToken, result); + await Fetch(myItem, cancellationToken, result).ConfigureAwait(false); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } @@ -51,22 +56,19 @@ namespace MediaBrowser.Providers.MediaInfo /// <param name="audio">The audio.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="data">The data.</param> - /// <param name="isoMount">The iso mount.</param> /// <returns>Task.</returns> - protected void Fetch(Audio audio, CancellationToken cancellationToken, MediaInfoResult data) + protected Task Fetch(Audio audio, CancellationToken cancellationToken, MediaInfoResult data) { - if (data.streams == null) - { - Logger.Error("Audio item has no streams: " + audio.Path); - return; - } + var internalStreams = data.streams ?? new MediaStreamInfo[] { }; - audio.MediaStreams = data.streams.Select(s => GetMediaStream(s, data.format)) + var mediaStreams = internalStreams.Select(s => GetMediaStream(s, data.format)) .Where(i => i != null) .ToList(); + audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.Video); + // Get the first audio stream - var stream = data.streams.FirstOrDefault(s => s.codec_type.Equals("audio", StringComparison.OrdinalIgnoreCase)); + var stream = internalStreams.FirstOrDefault(s => s.codec_type.Equals("audio", StringComparison.OrdinalIgnoreCase)); if (stream != null) { @@ -90,6 +92,8 @@ namespace MediaBrowser.Providers.MediaInfo { FetchDataFromTags(audio, data.format.tags); } + + return _itemRepo.SaveMediaStreams(audio.Id, mediaStreams, cancellationToken); } /// <summary> diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs index 4fb65a764..7e3e3da3b 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs @@ -138,7 +138,7 @@ namespace MediaBrowser.Providers.MediaInfo base.OnPreFetch(item, mount); } - public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var video = (Video)item; @@ -154,7 +154,7 @@ namespace MediaBrowser.Providers.MediaInfo if (video.PlayableStreamFileNames.Count == 0) { Logger.Error("No playable vobs found in dvd structure, skipping ffprobe."); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } } @@ -167,7 +167,7 @@ namespace MediaBrowser.Providers.MediaInfo cancellationToken.ThrowIfCancellationRequested(); - await Fetch(video, force, cancellationToken, result, isoMount).ConfigureAwait(false); + await Fetch(video, force, providerInfo, cancellationToken, result, isoMount).ConfigureAwait(false); } finally @@ -178,7 +178,7 @@ namespace MediaBrowser.Providers.MediaInfo } } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } @@ -291,7 +291,7 @@ namespace MediaBrowser.Providers.MediaInfo /// <param name="data">The data.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>Task.</returns> - protected async Task Fetch(Video video, bool force, CancellationToken cancellationToken, MediaInfoResult data, IIsoMount isoMount) + protected async Task Fetch(Video video, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken, MediaInfoResult data, IIsoMount isoMount) { if (data.format != null) { @@ -304,11 +304,17 @@ namespace MediaBrowser.Providers.MediaInfo } } + List<MediaStream> mediaStreams; + if (data.streams != null) { - video.MediaStreams = data.streams.Select(s => GetMediaStream(s, data.format)) - .Where(i => i != null) - .ToList(); + mediaStreams = data.streams.Select(s => GetMediaStream(s, data.format)) + .Where(i => i != null) + .ToList(); + } + else + { + mediaStreams = new List<MediaStream>(); } var chapters = data.Chapters ?? new List<ChapterInfo>(); @@ -316,30 +322,32 @@ namespace MediaBrowser.Providers.MediaInfo if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay)) { var inputPath = isoMount != null ? isoMount.MountedPath : video.Path; - FetchBdInfo(video, chapters, inputPath, cancellationToken); + FetchBdInfo(video, chapters, mediaStreams, inputPath, cancellationToken); } - AddExternalSubtitles(video); + AddExternalSubtitles(video, mediaStreams); FetchWtvInfo(video, force, data); - video.IsHD = video.MediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270); + video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270); - if (chapters.Count == 0 && video.MediaStreams.Any(i => i.Type == MediaStreamType.Video)) + if (chapters.Count == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video)) { AddDummyChapters(video, chapters); } - await Kernel.Instance.FFMpegManager.PopulateChapterImages(video, chapters, false, false, cancellationToken).ConfigureAwait(false); + var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); + video.VideoBitRate = videoStream == null ? null : videoStream.BitRate; + video.DefaultVideoStreamIndex = videoStream == null ? (int?)null : videoStream.Index; - BaseProviderInfo providerInfo; - var videoFileChanged = false; + video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle); - if (video.ProviderData.TryGetValue(Id, out providerInfo)) - { - videoFileChanged = CompareDate(video) > providerInfo.LastRefreshed; - } + await Kernel.Instance.FFMpegManager.PopulateChapterImages(video, chapters, false, false, cancellationToken).ConfigureAwait(false); + + var videoFileChanged = CompareDate(video) > providerInfo.LastRefreshed; + + await _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken).ConfigureAwait(false); // Only save chapters if forcing, if the video changed, or if there are not already any saved ones if (force || videoFileChanged || _itemRepo.GetChapter(video.Id, 0) == null) @@ -439,7 +447,8 @@ namespace MediaBrowser.Providers.MediaInfo /// Adds the external subtitles. /// </summary> /// <param name="video">The video.</param> - private void AddExternalSubtitles(Video video) + /// <param name="currentStreams">The current streams.</param> + private void AddExternalSubtitles(Video video, List<MediaStream> currentStreams) { var useParent = !video.ResolveArgs.IsDirectory; @@ -452,7 +461,7 @@ namespace MediaBrowser.Providers.MediaInfo ? video.Parent.ResolveArgs.FileSystemChildren : video.ResolveArgs.FileSystemChildren; - var startIndex = video.MediaStreams == null ? 0 : video.MediaStreams.Count; + var startIndex = currentStreams.Count; var streams = new List<MediaStream>(); var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path); @@ -503,11 +512,7 @@ namespace MediaBrowser.Providers.MediaInfo } } - if (video.MediaStreams == null) - { - video.MediaStreams = new List<MediaStream>(); - } - video.MediaStreams.AddRange(streams); + currentStreams.AddRange(streams); } /// <summary> @@ -556,9 +561,10 @@ namespace MediaBrowser.Providers.MediaInfo /// </summary> /// <param name="item">The item.</param> /// <param name="chapters">The chapters.</param> + /// <param name="mediaStreams">The media streams.</param> /// <param name="inputPath">The input path.</param> /// <param name="cancellationToken">The cancellation token.</param> - private void FetchBdInfo(BaseItem item, List<ChapterInfo> chapters, string inputPath, CancellationToken cancellationToken) + private void FetchBdInfo(BaseItem item, List<ChapterInfo> chapters, List<MediaStream> mediaStreams, string inputPath, CancellationToken cancellationToken) { var video = (Video)item; @@ -570,7 +576,7 @@ namespace MediaBrowser.Providers.MediaInfo int? currentWidth = null; int? currentBitRate = null; - var videoStream = video.MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video); + var videoStream = mediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video); // Grab the values that ffprobe recorded if (videoStream != null) @@ -581,9 +587,9 @@ namespace MediaBrowser.Providers.MediaInfo } // Fill video properties from the BDInfo result - Fetch(video, result, chapters); + Fetch(video, mediaStreams, result, chapters); - videoStream = video.MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video); + videoStream = mediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video); // Use the ffprobe values if these are empty if (videoStream != null) @@ -608,13 +614,15 @@ namespace MediaBrowser.Providers.MediaInfo /// Fills video properties from the VideoStream of the largest playlist /// </summary> /// <param name="video">The video.</param> + /// <param name="mediaStreams">The media streams.</param> /// <param name="stream">The stream.</param> /// <param name="chapters">The chapters.</param> - private void Fetch(Video video, BlurayDiscInfo stream, List<ChapterInfo> chapters) + private void Fetch(Video video, List<MediaStream> mediaStreams, BlurayDiscInfo stream, List<ChapterInfo> chapters) { // Check all input for null/empty/zero - video.MediaStreams = stream.MediaStreams; + mediaStreams.Clear(); + mediaStreams.AddRange(stream.MediaStreams); video.MainFeaturePlaylistName = stream.PlaylistName; diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index b57742042..2864983ce 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -128,7 +128,7 @@ namespace MediaBrowser.Providers.MediaInfo } // Can't extract if we didn't find a video stream in the file - if (item.MediaStreams.All(m => m.Type != MediaStreamType.Video)) + if (!item.DefaultVideoStreamIndex.HasValue) { return false; } @@ -171,7 +171,7 @@ namespace MediaBrowser.Providers.MediaInfo /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { item.ValidateImages(); @@ -192,7 +192,7 @@ namespace MediaBrowser.Providers.MediaInfo } } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs b/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs index 0b2502ba9..7c88243b3 100644 --- a/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs +++ b/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs @@ -18,14 +18,12 @@ namespace MediaBrowser.Providers.Movies /// </summary> public class BoxSetProviderFromXml : BaseMetadataProvider { - public static BoxSetProviderFromXml Current; private readonly IFileSystem _fileSystem; public BoxSetProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -57,7 +55,7 @@ namespace MediaBrowser.Providers.Movies return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -67,18 +65,7 @@ namespace MediaBrowser.Providers.Movies /// <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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -99,7 +86,7 @@ namespace MediaBrowser.Providers.Movies XmlParsingResourcePool.Release(); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs index be195d6d2..e483b1d61 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs @@ -187,7 +187,7 @@ namespace MediaBrowser.Providers.Movies /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -208,7 +208,7 @@ namespace MediaBrowser.Providers.Movies await FetchImages(item, images.ToList(), cancellationToken).ConfigureAwait(false); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs index d2a12ac21..d63fcec5c 100644 --- a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs @@ -164,13 +164,13 @@ namespace MediaBrowser.Providers.Movies /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualMovieDbImageProvider.ProviderName).ConfigureAwait(false); await ProcessImages(item, images.ToList(), cancellationToken).ConfigureAwait(false); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Movies/MovieDbPersonImageProvider.cs b/MediaBrowser.Providers/Movies/MovieDbPersonImageProvider.cs index 43550c358..8fa2ea249 100644 --- a/MediaBrowser.Providers/Movies/MovieDbPersonImageProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbPersonImageProvider.cs @@ -161,13 +161,13 @@ namespace MediaBrowser.Providers.Movies /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualMovieDbPersonImageProvider.ProviderName).ConfigureAwait(false); await ProcessImages(item, images.ToList(), cancellationToken).ConfigureAwait(false); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Movies/MovieDbPersonProvider.cs b/MediaBrowser.Providers/Movies/MovieDbPersonProvider.cs index af9bef448..3efd8d7fe 100644 --- a/MediaBrowser.Providers/Movies/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbPersonProvider.cs @@ -91,7 +91,7 @@ namespace MediaBrowser.Providers.Movies return base.NeedsRefreshInternal(item, providerInfo); } - + protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo) { var provderId = item.GetProviderId(MetadataProviders.Tmdb); @@ -152,7 +152,7 @@ namespace MediaBrowser.Providers.Movies /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.Movies await FetchInfo(person, id, force, cancellationToken).ConfigureAwait(false); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index fb75a9499..ecf5a5951 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -252,7 +252,7 @@ namespace MediaBrowser.Providers.Movies /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -275,7 +275,7 @@ namespace MediaBrowser.Providers.Movies await FetchMovieData(item, id, force, cancellationToken).ConfigureAwait(false); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs index dfab655f1..bb1299f67 100644 --- a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs +++ b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs @@ -19,7 +19,6 @@ namespace MediaBrowser.Providers.Movies /// </summary> public class MovieProviderFromXml : BaseMetadataProvider { - internal static MovieProviderFromXml Current { get; private set; } private readonly IItemRepository _itemRepo; private readonly IFileSystem _fileSystem; @@ -28,7 +27,6 @@ namespace MediaBrowser.Providers.Movies { _itemRepo = itemRepo; _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -73,7 +71,7 @@ namespace MediaBrowser.Providers.Movies return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -83,18 +81,7 @@ namespace MediaBrowser.Providers.Movies /// <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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -116,7 +103,7 @@ namespace MediaBrowser.Providers.Movies } } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Movies/OpenMovieDatabaseProvider.cs b/MediaBrowser.Providers/Movies/OpenMovieDatabaseProvider.cs index d881859c6..379b7c62c 100644 --- a/MediaBrowser.Providers/Movies/OpenMovieDatabaseProvider.cs +++ b/MediaBrowser.Providers/Movies/OpenMovieDatabaseProvider.cs @@ -107,13 +107,13 @@ namespace MediaBrowser.Providers.Movies protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var imdbId = item.GetProviderId(MetadataProviders.Imdb); if (string.IsNullOrEmpty(imdbId)) { - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } @@ -174,7 +174,7 @@ namespace MediaBrowser.Providers.Movies ParseAdditionalMetadata(item, result); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs b/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs index 8de061b99..60722f980 100644 --- a/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs +++ b/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs @@ -1,7 +1,6 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Logging; using System; @@ -13,14 +12,12 @@ namespace MediaBrowser.Providers.Movies { class PersonProviderFromXml : BaseMetadataProvider { - internal static PersonProviderFromXml Current { get; private set; } private readonly IFileSystem _fileSystem; public PersonProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -52,7 +49,7 @@ namespace MediaBrowser.Providers.Movies return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -62,18 +59,7 @@ namespace MediaBrowser.Providers.Movies /// <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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -94,7 +80,7 @@ namespace MediaBrowser.Providers.Movies XmlParsingResourcePool.Release(); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Music/AlbumInfoFromSongProvider.cs b/MediaBrowser.Providers/Music/AlbumInfoFromSongProvider.cs index da49d36ed..c4b4af97f 100644 --- a/MediaBrowser.Providers/Music/AlbumInfoFromSongProvider.cs +++ b/MediaBrowser.Providers/Music/AlbumInfoFromSongProvider.cs @@ -84,17 +84,10 @@ namespace MediaBrowser.Providers.Music return string.Join(string.Empty, albumArtistNames.OrderBy(i => i).ToArray()).GetMD5(); } - public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var album = (MusicAlbum)item; - BaseProviderInfo data; - if (!item.ProviderData.TryGetValue(Id, out data)) - { - data = new BaseProviderInfo(); - item.ProviderData[Id] = data; - } - var songs = album.RecursiveChildren.OfType<Audio>().ToList(); if (!item.LockedFields.Contains(MetadataFields.Name)) @@ -148,9 +141,9 @@ namespace MediaBrowser.Providers.Music } - data.FileStamp = GetComparisonData(songs); + providerInfo.FileStamp = GetComparisonData(songs); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return TrueTaskResult; } diff --git a/MediaBrowser.Providers/Music/AlbumProviderFromXml.cs b/MediaBrowser.Providers/Music/AlbumProviderFromXml.cs index 1dc4abfc8..32d45d1ae 100644 --- a/MediaBrowser.Providers/Music/AlbumProviderFromXml.cs +++ b/MediaBrowser.Providers/Music/AlbumProviderFromXml.cs @@ -14,14 +14,12 @@ namespace MediaBrowser.Providers.Music { class AlbumProviderFromXml : BaseMetadataProvider { - public static AlbumProviderFromXml Current; private readonly IFileSystem _fileSystem; public AlbumProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -53,7 +51,7 @@ namespace MediaBrowser.Providers.Music return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -63,18 +61,7 @@ namespace MediaBrowser.Providers.Music /// <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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -95,7 +82,7 @@ namespace MediaBrowser.Providers.Music XmlParsingResourcePool.Release(); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Music/ArtistInfoFromSongProvider.cs b/MediaBrowser.Providers/Music/ArtistInfoFromSongProvider.cs index 7069e65ef..05f7d4efe 100644 --- a/MediaBrowser.Providers/Music/ArtistInfoFromSongProvider.cs +++ b/MediaBrowser.Providers/Music/ArtistInfoFromSongProvider.cs @@ -61,19 +61,12 @@ namespace MediaBrowser.Providers.Music return string.Join(string.Empty, genres.OrderBy(i => i).ToArray()).GetMD5(); } - public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var artist = (MusicArtist)item; if (!artist.IsAccessedByName) { - BaseProviderInfo data; - if (!item.ProviderData.TryGetValue(Id, out data)) - { - data = new BaseProviderInfo(); - item.ProviderData[Id] = data; - } - var songs = artist.RecursiveChildren.OfType<Audio>().ToList(); if (!item.LockedFields.Contains(MetadataFields.Genres)) @@ -83,10 +76,10 @@ namespace MediaBrowser.Providers.Music .ToList(); } - data.FileStamp = GetComparisonData(songs); + providerInfo.FileStamp = GetComparisonData(songs); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return TrueTaskResult; } diff --git a/MediaBrowser.Providers/Music/ArtistProviderFromXml.cs b/MediaBrowser.Providers/Music/ArtistProviderFromXml.cs index b7e846353..a25fd0093 100644 --- a/MediaBrowser.Providers/Music/ArtistProviderFromXml.cs +++ b/MediaBrowser.Providers/Music/ArtistProviderFromXml.cs @@ -14,14 +14,12 @@ namespace MediaBrowser.Providers.Music { class ArtistProviderFromXml : BaseMetadataProvider { - public static ArtistProviderFromXml Current; private readonly IFileSystem _fileSystem; public ArtistProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -53,7 +51,7 @@ namespace MediaBrowser.Providers.Music return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -63,18 +61,7 @@ namespace MediaBrowser.Providers.Music /// <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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -95,7 +82,7 @@ namespace MediaBrowser.Providers.Music XmlParsingResourcePool.Release(); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs index a49de9a29..161c96a5d 100644 --- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs @@ -152,13 +152,13 @@ namespace MediaBrowser.Providers.Music /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualFanartAlbumProvider.ProviderName).ConfigureAwait(false); await FetchFromXml(item, images.ToList(), cancellationToken).ConfigureAwait(false); - - SetLastRefreshed(item, DateTime.UtcNow); + + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs index 1b0a80d9a..4830d15b1 100644 --- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs @@ -197,7 +197,7 @@ namespace MediaBrowser.Providers.Music /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -223,7 +223,7 @@ namespace MediaBrowser.Providers.Music await FetchFromXml(item, images.ToList(), cancellationToken).ConfigureAwait(false); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Music/LastFmImageProvider.cs b/MediaBrowser.Providers/Music/LastFmImageProvider.cs index a2ae597d7..2a30a3a2e 100644 --- a/MediaBrowser.Providers/Music/LastFmImageProvider.cs +++ b/MediaBrowser.Providers/Music/LastFmImageProvider.cs @@ -68,7 +68,7 @@ namespace MediaBrowser.Providers.Music /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { if (!item.HasImage(ImageType.Primary)) { @@ -77,7 +77,7 @@ namespace MediaBrowser.Providers.Music await DownloadImages(item, images.ToList(), cancellationToken).ConfigureAwait(false); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs b/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs index 3c6bc19be..04946fabc 100644 --- a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Providers.Music /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -92,17 +92,10 @@ namespace MediaBrowser.Providers.Music { LastfmHelper.ProcessAlbumData(item, result.album); } - - BaseProviderInfo data; - if (!item.ProviderData.TryGetValue(Id, out data)) - { - data = new BaseProviderInfo(); - item.ProviderData[Id] = data; - } - data.FileStamp = GetComparisonData(album); + providerInfo.FileStamp = GetComparisonData(album); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs b/MediaBrowser.Providers/Music/LastfmArtistProvider.cs index ae14d62c7..02babb4e6 100644 --- a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs +++ b/MediaBrowser.Providers/Music/LastfmArtistProvider.cs @@ -108,7 +108,7 @@ namespace MediaBrowser.Providers.Music /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -123,7 +123,7 @@ namespace MediaBrowser.Providers.Music await FetchLastfmData(item, id, force, cancellationToken).ConfigureAwait(false); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index c01b445ca..e678271f2 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Providers.Music return item is MusicAlbum; } - public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var releaseId = item.GetProviderId(MetadataProviders.Musicbrainz); var releaseGroupId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); @@ -64,7 +64,7 @@ namespace MediaBrowser.Providers.Music item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, releaseGroupId); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs b/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs index 6e8083508..8dd6940c5 100644 --- a/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs @@ -59,9 +59,6 @@ namespace MediaBrowser.Providers.Savers var xmlFilePath = GetSavePath(item); XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }); - - // Set last refreshed so that the provider doesn't trigger after the file save - AlbumProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs b/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs index 81f092a46..924a5a88e 100644 --- a/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs @@ -72,9 +72,6 @@ namespace MediaBrowser.Providers.Savers var xmlFilePath = GetSavePath(item); XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }); - - // Set last refreshed so that the provider doesn't trigger after the file save - ArtistProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs b/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs index cec6da64a..c2e607f6a 100644 --- a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs @@ -59,8 +59,6 @@ namespace MediaBrowser.Providers.Savers var xmlFilePath = GetSavePath(item); XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }); - - BoxSetProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs b/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs index c6ac220a9..6880c9948 100644 --- a/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs @@ -56,9 +56,6 @@ namespace MediaBrowser.Providers.Savers XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }); - - // Set last refreshed so that the provider doesn't trigger after the file save - ChannelProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs index 1c37b0789..35dd551f1 100644 --- a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs @@ -3,8 +3,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; -using MediaBrowser.Providers.TV; -using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -117,9 +115,6 @@ namespace MediaBrowser.Providers.Savers "airsbefore_episode", "airsbefore_season" }); - - // Set last refreshed so that the provider doesn't trigger after the file save - EpisodeProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs b/MediaBrowser.Providers/Savers/FolderXmlSaver.cs index 319f6c7d0..9c1e6f38e 100644 --- a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/FolderXmlSaver.cs @@ -4,7 +4,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; -using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -78,8 +77,6 @@ namespace MediaBrowser.Providers.Savers var xmlFilePath = GetSavePath(item); XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }); - - FolderProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs b/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs index 724e3b1d9..496bb51d0 100644 --- a/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs @@ -58,8 +58,6 @@ namespace MediaBrowser.Providers.Savers var xmlFilePath = GetSavePath(item); XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }); - - GameSystemProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/GameXmlSaver.cs b/MediaBrowser.Providers/Savers/GameXmlSaver.cs index f35e4d131..03c3a2916 100644 --- a/MediaBrowser.Providers/Savers/GameXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/GameXmlSaver.cs @@ -98,9 +98,6 @@ namespace MediaBrowser.Providers.Savers "NesBox", "NesBoxRom" }); - - // Set last refreshed so that the provider doesn't trigger after the file save - MovieProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } public string GetSavePath(BaseItem item) diff --git a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs b/MediaBrowser.Providers/Savers/MovieXmlSaver.cs index 1a287a918..17dca6008 100644 --- a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/MovieXmlSaver.cs @@ -122,9 +122,6 @@ namespace MediaBrowser.Providers.Savers "Album", "TmdbCollectionName" }); - - // Set last refreshed so that the provider doesn't trigger after the file save - MovieProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } public string GetSavePath(BaseItem item) diff --git a/MediaBrowser.Providers/Savers/PersonXmlSaver.cs b/MediaBrowser.Providers/Savers/PersonXmlSaver.cs index cefdec9c1..a6d7575ea 100644 --- a/MediaBrowser.Providers/Savers/PersonXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/PersonXmlSaver.cs @@ -64,9 +64,6 @@ namespace MediaBrowser.Providers.Savers { "PlaceOfBirth" }); - - // Set last refreshed so that the provider doesn't trigger after the file save - PersonProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs b/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs index a2231ab74..c96f71b0a 100644 --- a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs @@ -2,8 +2,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; -using MediaBrowser.Providers.TV; -using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -59,8 +57,6 @@ namespace MediaBrowser.Providers.Savers var xmlFilePath = GetSavePath(item); XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }); - - SeasonProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs b/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs index b955ac7c9..7f37ba1ce 100644 --- a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs @@ -3,8 +3,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; -using MediaBrowser.Providers.TV; -using System; using System.Collections.Generic; using System.IO; using System.Security; @@ -119,9 +117,6 @@ namespace MediaBrowser.Providers.Savers // Don't preserve old series node "Series" }); - - // Set last refreshed so that the provider doesn't trigger after the file save - SeriesProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow); } /// <summary> diff --git a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs index a4e4ce1a8..522b2c90b 100644 --- a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs +++ b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs @@ -529,8 +529,6 @@ namespace MediaBrowser.Providers.Savers /// Appends the media info. /// </summary> /// <typeparam name="T"></typeparam> - /// <param name="item">The item.</param> - /// <param name="builder">The builder.</param> public static void AddMediaInfo<T>(T item, StringBuilder builder, IItemRepository itemRepository) where T : BaseItem, IHasMediaStreams { @@ -538,105 +536,38 @@ namespace MediaBrowser.Providers.Savers builder.Append("<MediaInfo>"); - foreach (var stream in item.MediaStreams) - { - builder.Append("<" + stream.Type + ">"); - - if (!string.IsNullOrEmpty(stream.Codec)) - { - builder.Append("<Codec>" + SecurityElement.Escape(stream.Codec) + "</Codec>"); - builder.Append("<FFCodec>" + SecurityElement.Escape(stream.Codec) + "</FFCodec>"); - } - - if (stream.BitRate.HasValue) - { - builder.Append("<BitRate>" + stream.BitRate.Value.ToString(UsCulture) + "</BitRate>"); - } - - if (stream.Width.HasValue) - { - builder.Append("<Width>" + stream.Width.Value.ToString(UsCulture) + "</Width>"); - } - - if (stream.Height.HasValue) - { - builder.Append("<Height>" + stream.Height.Value.ToString(UsCulture) + "</Height>"); - } - - if (!string.IsNullOrEmpty(stream.AspectRatio)) - { - builder.Append("<AspectRatio>" + SecurityElement.Escape(stream.AspectRatio) + "</AspectRatio>"); - } - - var framerate = stream.AverageFrameRate ?? stream.RealFrameRate; - - if (framerate.HasValue) - { - builder.Append("<FrameRate>" + framerate.Value.ToString(UsCulture) + "</FrameRate>"); - } - - if (!string.IsNullOrEmpty(stream.Language)) - { - builder.Append("<Language>" + SecurityElement.Escape(stream.Language) + "</Language>"); - } + builder.Append("<Video>"); - if (!string.IsNullOrEmpty(stream.ScanType)) - { - builder.Append("<ScanType>" + SecurityElement.Escape(stream.ScanType) + "</ScanType>"); - } - - if (stream.Channels.HasValue) - { - builder.Append("<Channels>" + stream.Channels.Value.ToString(UsCulture) + "</Channels>"); - } - - if (stream.SampleRate.HasValue) - { - builder.Append("<SamplingRate>" + stream.SampleRate.Value.ToString(UsCulture) + "</SamplingRate>"); - } + if (item.RunTimeTicks.HasValue) + { + var timespan = TimeSpan.FromTicks(item.RunTimeTicks.Value); - builder.Append("<Default>" + SecurityElement.Escape(stream.IsDefault.ToString()) + "</Default>"); - builder.Append("<Forced>" + SecurityElement.Escape(stream.IsForced.ToString()) + "</Forced>"); + builder.Append("<Duration>" + Convert.ToInt64(timespan.TotalMinutes).ToString(UsCulture) + "</Duration>"); + builder.Append("<DurationSeconds>" + Convert.ToInt64(timespan.TotalSeconds).ToString(UsCulture) + "</DurationSeconds>"); + } - if (stream.Type == MediaStreamType.Video) + if (video != null && video.Video3DFormat.HasValue) + { + switch (video.Video3DFormat.Value) { - if (item.RunTimeTicks.HasValue) - { - var timespan = TimeSpan.FromTicks(item.RunTimeTicks.Value); - - builder.Append("<Duration>" + Convert.ToInt64(timespan.TotalMinutes).ToString(UsCulture) + "</Duration>"); - builder.Append("<DurationSeconds>" + Convert.ToInt64(timespan.TotalSeconds).ToString(UsCulture) + "</DurationSeconds>"); - } - - if (video != null && video.Video3DFormat.HasValue) - { - switch (video.Video3DFormat.Value) - { - case Video3DFormat.FullSideBySide: - builder.Append("<Format3D>FSBS</Format3D>"); - break; - case Video3DFormat.FullTopAndBottom: - builder.Append("<Format3D>FTAB</Format3D>"); - break; - case Video3DFormat.HalfSideBySide: - builder.Append("<Format3D>HSBS</Format3D>"); - break; - case Video3DFormat.HalfTopAndBottom: - builder.Append("<Format3D>HTAB</Format3D>"); - break; - } - } + case Video3DFormat.FullSideBySide: + builder.Append("<Format3D>FSBS</Format3D>"); + break; + case Video3DFormat.FullTopAndBottom: + builder.Append("<Format3D>FTAB</Format3D>"); + break; + case Video3DFormat.HalfSideBySide: + builder.Append("<Format3D>HSBS</Format3D>"); + break; + case Video3DFormat.HalfTopAndBottom: + builder.Append("<Format3D>HTAB</Format3D>"); + break; } - - builder.Append("</" + stream.Type + ">"); } - builder.Append("</MediaInfo>"); + builder.Append("</Video>"); - if (video != null) - { - //AddChapters(video, builder, itemRepository); - } + builder.Append("</MediaInfo>"); } } } diff --git a/MediaBrowser.Providers/TV/EpisodeImageFromMediaLocationProvider.cs b/MediaBrowser.Providers/TV/EpisodeImageFromMediaLocationProvider.cs index 00e836936..83d36bb3c 100644 --- a/MediaBrowser.Providers/TV/EpisodeImageFromMediaLocationProvider.cs +++ b/MediaBrowser.Providers/TV/EpisodeImageFromMediaLocationProvider.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Providers.TV /// <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) + public override Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -96,7 +96,7 @@ namespace MediaBrowser.Providers.TV SetPrimaryImagePath(episode, parent, item.MetaLocation, episodeFileName); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return TrueTaskResult; } diff --git a/MediaBrowser.Providers/TV/EpisodeIndexNumberProvider.cs b/MediaBrowser.Providers/TV/EpisodeIndexNumberProvider.cs index 592c5dcac..4427e60e4 100644 --- a/MediaBrowser.Providers/TV/EpisodeIndexNumberProvider.cs +++ b/MediaBrowser.Providers/TV/EpisodeIndexNumberProvider.cs @@ -60,7 +60,7 @@ namespace MediaBrowser.Providers.TV /// <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) + public override Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var episode = (Episode)item; @@ -77,7 +77,7 @@ namespace MediaBrowser.Providers.TV } } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return TrueTaskResult; } diff --git a/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs b/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs index 7ddf421b9..38921c008 100644 --- a/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs +++ b/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs @@ -18,7 +18,6 @@ namespace MediaBrowser.Providers.TV /// </summary> public class EpisodeProviderFromXml : BaseMetadataProvider { - internal static EpisodeProviderFromXml Current { get; private set; } private readonly IItemRepository _itemRepo; private readonly IFileSystem _fileSystem; @@ -27,7 +26,6 @@ namespace MediaBrowser.Providers.TV { _itemRepo = itemRepo; _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -56,61 +54,50 @@ namespace MediaBrowser.Providers.TV /// <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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { - return Fetch(item, cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); - /// <summary> - /// Needses the refresh based on compare date. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="providerInfo">The provider info.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo) - { var metadataFile = Path.Combine(item.MetaLocation, Path.ChangeExtension(Path.GetFileName(item.Path), ".xml")); var file = item.ResolveArgs.Parent.ResolveArgs.GetMetaFileByPath(metadataFile); - if (file == null) + if (file != null) { - return false; + await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + await new EpisodeXmlParser(Logger, _itemRepo).FetchAsync((Episode)item, metadataFile, cancellationToken).ConfigureAwait(false); + } + finally + { + XmlParsingResourcePool.Release(); + } } - return _fileSystem.GetLastWriteTimeUtc(file) > providerInfo.LastRefreshed; + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); + return true; } /// <summary> - /// Fetches the specified item. + /// Needses the refresh based on compare date. /// </summary> /// <param name="item">The item.</param> - /// <param name="cancellationToken">The cancellation token.</param> + /// <param name="providerInfo">The provider info.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - private async Task<bool> Fetch(BaseItem item, CancellationToken cancellationToken) + protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo) { - cancellationToken.ThrowIfCancellationRequested(); - var metadataFile = Path.Combine(item.MetaLocation, Path.ChangeExtension(Path.GetFileName(item.Path), ".xml")); var file = item.ResolveArgs.Parent.ResolveArgs.GetMetaFileByPath(metadataFile); - if (file != null) + if (file == null) { - await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - await new EpisodeXmlParser(Logger, _itemRepo).FetchAsync((Episode)item, metadataFile, cancellationToken).ConfigureAwait(false); - } - finally - { - XmlParsingResourcePool.Release(); - } + return false; } - SetLastRefreshed(item, DateTime.UtcNow); - return true; + return _fileSystem.GetLastWriteTimeUtc(file) > item.DateLastSaved; } } } diff --git a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs index bf52ca349..ed5145bc2 100644 --- a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.Providers.TV /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -108,7 +108,7 @@ namespace MediaBrowser.Providers.TV await FetchImages(season, images.ToList(), cancellationToken).ConfigureAwait(false); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/TV/FanArtTVProvider.cs b/MediaBrowser.Providers/TV/FanArtTVProvider.cs index 037e0b5bc..251420261 100644 --- a/MediaBrowser.Providers/TV/FanArtTVProvider.cs +++ b/MediaBrowser.Providers/TV/FanArtTVProvider.cs @@ -160,8 +160,8 @@ namespace MediaBrowser.Providers.TV } protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -182,7 +182,7 @@ namespace MediaBrowser.Providers.TV await FetchFromXml(item, images.ToList(), cancellationToken).ConfigureAwait(false); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs b/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs index 5f1eb5cb3..2127234dc 100644 --- a/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs +++ b/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs @@ -18,14 +18,12 @@ namespace MediaBrowser.Providers.TV /// </summary> public class SeasonProviderFromXml : BaseMetadataProvider { - public static SeasonProviderFromXml Current; private readonly IFileSystem _fileSystem; public SeasonProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -57,7 +55,7 @@ namespace MediaBrowser.Providers.TV return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -67,18 +65,7 @@ namespace MediaBrowser.Providers.TV /// <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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -99,7 +86,7 @@ namespace MediaBrowser.Providers.TV XmlParsingResourcePool.Release(); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/TV/SeriesDynamicInfoProvider.cs b/MediaBrowser.Providers/TV/SeriesDynamicInfoProvider.cs index 59faaa931..ff31ce4aa 100644 --- a/MediaBrowser.Providers/TV/SeriesDynamicInfoProvider.cs +++ b/MediaBrowser.Providers/TV/SeriesDynamicInfoProvider.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Providers.TV return item is Series; } - public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var series = (Series)item; diff --git a/MediaBrowser.Providers/TV/SeriesProviderFromXml.cs b/MediaBrowser.Providers/TV/SeriesProviderFromXml.cs index c4b82d51e..ff99a95c1 100644 --- a/MediaBrowser.Providers/TV/SeriesProviderFromXml.cs +++ b/MediaBrowser.Providers/TV/SeriesProviderFromXml.cs @@ -18,14 +18,12 @@ namespace MediaBrowser.Providers.TV /// </summary> public class SeriesProviderFromXml : BaseMetadataProvider { - internal static SeriesProviderFromXml Current { get; private set; } private readonly IFileSystem _fileSystem; public SeriesProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _fileSystem = fileSystem; - Current = this; } /// <summary> @@ -57,7 +55,7 @@ namespace MediaBrowser.Providers.TV return false; } - return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; } /// <summary> @@ -67,21 +65,10 @@ namespace MediaBrowser.Providers.TV /// <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) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - + var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, XmlFileName)); if (metadataFile != null) @@ -99,12 +86,10 @@ namespace MediaBrowser.Providers.TV XmlParsingResourcePool.Release(); } - SetLastRefreshed(item, DateTime.UtcNow); - - return true; } - return false; + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); + return true; } } } diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs index 54e446380..5d9f387fe 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs @@ -242,7 +242,7 @@ namespace MediaBrowser.Providers.TV /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -266,7 +266,7 @@ namespace MediaBrowser.Providers.TV } } - SetLastRefreshed(item, DateTime.UtcNow, status); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo, status); return true; } diff --git a/MediaBrowser.Providers/TV/TvdbPersonImageProvider.cs b/MediaBrowser.Providers/TV/TvdbPersonImageProvider.cs index 53f1c7bdb..3a503ea20 100644 --- a/MediaBrowser.Providers/TV/TvdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbPersonImageProvider.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Providers.TV /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(item.PrimaryImagePath)) { @@ -68,11 +68,11 @@ namespace MediaBrowser.Providers.TV await DownloadImages(item, images.ToList(), cancellationToken).ConfigureAwait(false); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } private async Task DownloadImages(BaseItem item, List<RemoteImageInfo> images, CancellationToken cancellationToken) diff --git a/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs index 05fee7861..cdfe86dac 100644 --- a/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs @@ -141,7 +141,7 @@ namespace MediaBrowser.Providers.TV /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -151,7 +151,7 @@ namespace MediaBrowser.Providers.TV await DownloadImages(item, images.ToList(), backdropLimit, cancellationToken).ConfigureAwait(false); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs index b56b50bec..c1ac0e386 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs @@ -151,7 +151,7 @@ namespace MediaBrowser.Providers.TV /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -161,7 +161,7 @@ namespace MediaBrowser.Providers.TV await DownloadImages(item, images.ToList(), backdropLimit, cancellationToken).ConfigureAwait(false); - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index 29e191a59..5691f885e 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -205,7 +205,7 @@ namespace MediaBrowser.Providers.TV /// <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 async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -227,7 +227,7 @@ namespace MediaBrowser.Providers.TV await FetchSeriesData(series, seriesId, seriesDataPath, force, cancellationToken).ConfigureAwait(false); } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Providers/UserRootFolderNameProvider.cs b/MediaBrowser.Providers/UserRootFolderNameProvider.cs index 513020213..551dd4257 100644 --- a/MediaBrowser.Providers/UserRootFolderNameProvider.cs +++ b/MediaBrowser.Providers/UserRootFolderNameProvider.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Providers return item is UserRootFolder; } - public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var parentName = Path.GetFileNameWithoutExtension(item.Path); @@ -30,7 +30,7 @@ namespace MediaBrowser.Providers item.Name = "Media Library"; } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return TrueTaskResult; } diff --git a/MediaBrowser.Server.Implementations/BdInfo/BdInfoExaminer.cs b/MediaBrowser.Server.Implementations/BdInfo/BdInfoExaminer.cs index 06768f353..18f1b92fe 100644 --- a/MediaBrowser.Server.Implementations/BdInfo/BdInfoExaminer.cs +++ b/MediaBrowser.Server.Implementations/BdInfo/BdInfoExaminer.cs @@ -102,7 +102,7 @@ namespace MediaBrowser.Server.Implementations.BdInfo Width = videoStream.Width, Height = videoStream.Height, Codec = videoStream.CodecShortName, - ScanType = videoStream.IsInterlaced ? "interlaced" : "progressive", + IsInterlaced = videoStream.IsInterlaced, Type = MediaStreamType.Video, Index = streams.Count }; @@ -146,7 +146,7 @@ namespace MediaBrowser.Server.Implementations.BdInfo { stream.Channels = audioStream.ChannelCount + 1; } - + streams.Add(stream); } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index bb9ee7e14..ba9dd170d 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1034,7 +1034,11 @@ namespace MediaBrowser.Server.Implementations.Dto if (iHasMediaStreams != null) { - dto.MediaStreams = iHasMediaStreams.MediaStreams; + dto.MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery + { + ItemId = item.Id + + }).ToList(); } } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 3b6a5ea25..41694765d 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1311,6 +1311,11 @@ namespace MediaBrowser.Server.Implementations.Library { var list = items.ToList(); + foreach (var item in list) + { + item.DateLastSaved = DateTime.UtcNow; + } + await ItemRepository.SaveItems(list, cancellationToken).ConfigureAwait(false); foreach (var item in list) @@ -1350,6 +1355,8 @@ namespace MediaBrowser.Server.Implementations.Library await SaveMetadata(item, updateReason).ConfigureAwait(false); } + item.DateLastSaved = DateTime.UtcNow; + await ItemRepository.SaveItem(item, cancellationToken).ConfigureAwait(false); UpdateItemInLibraryCache(item); diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 04d0f6ab2..4243aecfe 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -196,6 +196,8 @@ namespace MediaBrowser.Server.Implementations.Library var user = InstantiateNewUser(name); + user.DateLastSaved = DateTime.UtcNow; + var task = UserRepository.SaveUser(user, CancellationToken.None); // Hate having to block threads @@ -274,6 +276,7 @@ namespace MediaBrowser.Server.Implementations.Library } user.DateModified = DateTime.UtcNow; + user.DateLastSaved = DateTime.UtcNow; await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false); @@ -307,6 +310,8 @@ namespace MediaBrowser.Server.Implementations.Library list.Add(user); Users = list; + user.DateLastSaved = DateTime.UtcNow; + await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false); EventHelper.QueueEventIfNotNull(UserCreated, this, new GenericEventArgs<User> { Argument = user }, _logger); diff --git a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs index 322948bad..e16430e69 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs @@ -36,11 +36,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv return !item.HasImage(ImageType.Primary); } - public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { if (item.HasImage(ImageType.Primary)) { - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } @@ -58,7 +58,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv } - SetLastRefreshed(item, DateTime.UtcNow); + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 54fbb502e..4b30672d0 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -168,7 +168,9 @@ <Compile Include="MediaEncoder\MediaEncoder.cs" /> <Compile Include="Persistence\SqliteChapterRepository.cs" /> <Compile Include="Persistence\SqliteExtensions.cs" /> + <Compile Include="Persistence\SqliteMediaStreamsRepository.cs" /> <Compile Include="Persistence\SqliteNotificationsRepository.cs" /> + <Compile Include="Persistence\SqliteProviderInfoRepository.cs" /> <Compile Include="Persistence\TypeMapper.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Providers\ImageSaver.cs" /> diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fc2a6de24..893d6ea62 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; @@ -56,6 +57,8 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly string _criticReviewsPath; private SqliteChapterRepository _chapterRepository; + private SqliteMediaStreamsRepository _mediaStreamsRepository; + private SqliteProviderInfoRepository _providerInfoRepository; private IDbCommand _deleteChildrenCommand; private IDbCommand _saveChildrenCommand; @@ -90,10 +93,16 @@ namespace MediaBrowser.Server.Implementations.Persistence _logger = logManager.GetLogger(GetType().Name); var chapterDbFile = Path.Combine(_appPaths.DataPath, "chapters.db"); - var chapterConnection = SqliteExtensions.ConnectToDb(chapterDbFile, _logger).Result; - _chapterRepository = new SqliteChapterRepository(chapterConnection, logManager); + + var mediaStreamsDbFile = Path.Combine(_appPaths.DataPath, "mediainfo.db"); + var mediaStreamsConnection = SqliteExtensions.ConnectToDb(mediaStreamsDbFile, _logger).Result; + _mediaStreamsRepository = new SqliteMediaStreamsRepository(mediaStreamsConnection, logManager); + + var providerInfosDbFile = Path.Combine(_appPaths.DataPath, "providerinfo.db"); + var providerInfoConnection = SqliteExtensions.ConnectToDb(providerInfosDbFile, _logger).Result; + _providerInfoRepository = new SqliteProviderInfoRepository(providerInfoConnection, logManager); } /// <summary> @@ -121,7 +130,9 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.RunQueries(queries, _logger); PrepareStatements(); - + + _mediaStreamsRepository.Initialize(); + _providerInfoRepository.Initialize(); _chapterRepository.Initialize(); } @@ -413,6 +424,18 @@ namespace MediaBrowser.Server.Implementations.Persistence _chapterRepository.Dispose(); _chapterRepository = null; } + + if (_mediaStreamsRepository != null) + { + _mediaStreamsRepository.Dispose(); + _mediaStreamsRepository = null; + } + + if (_providerInfoRepository != null) + { + _providerInfoRepository.Dispose(); + _providerInfoRepository = null; + } } } @@ -511,5 +534,25 @@ namespace MediaBrowser.Server.Implementations.Persistence _writeLock.Release(); } } + + public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query) + { + return _mediaStreamsRepository.GetMediaStreams(query); + } + + public Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken) + { + return _mediaStreamsRepository.SaveMediaStreams(id, streams, cancellationToken); + } + + public IEnumerable<BaseProviderInfo> GetProviderHistory(Guid itemId) + { + return _providerInfoRepository.GetBaseProviderInfos(itemId); + } + + public Task SaveProviderHistory(Guid id, IEnumerable<BaseProviderInfo> history, CancellationToken cancellationToken) + { + return _providerInfoRepository.SaveProviderInfos(id, history, cancellationToken); + } } }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs new file mode 100644 index 000000000..ba189396a --- /dev/null +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs @@ -0,0 +1,377 @@ +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Persistence +{ + class SqliteMediaStreamsRepository + { + private IDbConnection _connection; + + private readonly ILogger _logger; + + private IDbCommand _deleteStreamsCommand; + private IDbCommand _saveStreamCommand; + + public SqliteMediaStreamsRepository(IDbConnection connection, ILogManager logManager) + { + _connection = connection; + + _logger = logManager.GetLogger(GetType().Name); + } + + /// <summary> + /// Opens the connection to the database + /// </summary> + /// <returns>Task.</returns> + public void Initialize() + { + var createTableCommand + = "create table if not exists mediastreams "; + + createTableCommand += "(ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + + string[] queries = { + + createTableCommand, + "create index if not exists idx_mediastreams on mediastreams(ItemId, StreamIndex)", + + //pragmas + "pragma temp_store = memory" + }; + + _connection.RunQueries(queries, _logger); + + PrepareStatements(); + } + + private readonly string[] _saveColumns = + { + "ItemId", + "StreamIndex", + "StreamType", + "Codec", + "Language", + "ChannelLayout", + "Profile", + "AspectRatio", + "Path", + "IsInterlaced", + "BitRate", + "Channels", + "SampleRate", + "IsDefault", + "IsForced", + "IsExternal", + "Height", + "Width", + "AverageFrameRate", + "RealFrameRate", + "Level" + }; + + /// <summary> + /// The _write lock + /// </summary> + private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1); + + /// <summary> + /// Prepares the statements. + /// </summary> + private void PrepareStatements() + { + _deleteStreamsCommand = _connection.CreateCommand(); + _deleteStreamsCommand.CommandText = "delete from mediastreams where ItemId=@ItemId"; + _deleteStreamsCommand.Parameters.Add(_deleteStreamsCommand, "@ItemId"); + + _saveStreamCommand = _connection.CreateCommand(); + + _saveStreamCommand.CommandText = string.Format("replace into mediastreams ({0}) values ({1})", + string.Join(",", _saveColumns), + string.Join(",", _saveColumns.Select(i => "@" + i).ToArray())); + + foreach (var col in _saveColumns) + { + _saveStreamCommand.Parameters.Add(_saveStreamCommand, "@" + col); + } + } + + public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query) + { + if (query == null) + { + throw new ArgumentNullException("query"); + } + + using (var cmd = _connection.CreateCommand()) + { + var cmdText = "select " + string.Join(",", _saveColumns) + " from mediastreams where"; + + cmdText += " ItemId=@ItemId"; + cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = query.ItemId; + + if (query.Type.HasValue) + { + cmdText += " AND StreamType=@StreamType"; + cmd.Parameters.Add(cmd, "@StreamType", DbType.String).Value = query.Type.Value.ToString(); + } + + if (query.Index.HasValue) + { + cmdText += " AND StreamIndex=@StreamIndex"; + cmd.Parameters.Add(cmd, "@StreamIndex", DbType.Int32).Value = query.Index.Value; + } + + cmdText += " order by StreamIndex ASC"; + + cmd.CommandText = cmdText; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + yield return GetMediaStream(reader); + } + } + } + } + + /// <summary> + /// Gets the chapter. + /// </summary> + /// <param name="reader">The reader.</param> + /// <returns>ChapterInfo.</returns> + private MediaStream GetMediaStream(IDataReader reader) + { + var item = new MediaStream + { + Index = reader.GetInt32(1) + }; + + item.Type = (MediaStreamType)Enum.Parse(typeof(MediaStreamType), reader.GetString(2), true); + + if (!reader.IsDBNull(3)) + { + item.Codec = reader.GetString(3); + } + + if (!reader.IsDBNull(4)) + { + item.Language = reader.GetString(4); + } + + if (!reader.IsDBNull(5)) + { + item.ChannelLayout = reader.GetString(5); + } + + if (!reader.IsDBNull(6)) + { + item.Profile = reader.GetString(6); + } + + if (!reader.IsDBNull(7)) + { + item.AspectRatio = reader.GetString(7); + } + + if (!reader.IsDBNull(8)) + { + item.Path = reader.GetString(8); + } + + item.IsInterlaced = reader.GetBoolean(9); + + if (!reader.IsDBNull(10)) + { + item.BitRate = reader.GetInt32(10); + } + + if (!reader.IsDBNull(11)) + { + item.Channels = reader.GetInt32(11); + } + + if (!reader.IsDBNull(12)) + { + item.SampleRate = reader.GetInt32(12); + } + + item.IsDefault = reader.GetBoolean(13); + item.IsForced = reader.GetBoolean(14); + item.IsExternal = reader.GetBoolean(15); + + if (!reader.IsDBNull(16)) + { + item.Width = reader.GetInt32(16); + } + + if (!reader.IsDBNull(17)) + { + item.Height = reader.GetInt32(17); + } + + if (!reader.IsDBNull(18)) + { + item.AverageFrameRate = reader.GetFloat(18); + } + + if (!reader.IsDBNull(19)) + { + item.RealFrameRate = reader.GetFloat(19); + } + + if (!reader.IsDBNull(20)) + { + item.Level = reader.GetFloat(20); + } + + return item; + } + + public async Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken) + { + if (id == Guid.Empty) + { + throw new ArgumentNullException("id"); + } + + if (streams == null) + { + throw new ArgumentNullException("streams"); + } + + cancellationToken.ThrowIfCancellationRequested(); + + await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + IDbTransaction transaction = null; + + try + { + transaction = _connection.BeginTransaction(); + + // First delete chapters + _deleteStreamsCommand.GetParameter(0).Value = id; + + _deleteStreamsCommand.Transaction = transaction; + + _deleteStreamsCommand.ExecuteNonQuery(); + + foreach (var stream in streams) + { + cancellationToken.ThrowIfCancellationRequested(); + + _saveStreamCommand.GetParameter(0).Value = id; + _saveStreamCommand.GetParameter(1).Value = stream.Index; + _saveStreamCommand.GetParameter(2).Value = stream.Type.ToString(); + _saveStreamCommand.GetParameter(3).Value = stream.Codec; + _saveStreamCommand.GetParameter(4).Value = stream.Language; + _saveStreamCommand.GetParameter(5).Value = stream.ChannelLayout; + _saveStreamCommand.GetParameter(6).Value = stream.Profile; + _saveStreamCommand.GetParameter(7).Value = stream.AspectRatio; + _saveStreamCommand.GetParameter(8).Value = stream.Path; + + _saveStreamCommand.GetParameter(9).Value = stream.IsInterlaced; + + _saveStreamCommand.GetParameter(10).Value = stream.BitRate; + _saveStreamCommand.GetParameter(11).Value = stream.Channels; + _saveStreamCommand.GetParameter(12).Value = stream.SampleRate; + + _saveStreamCommand.GetParameter(13).Value = stream.IsDefault; + _saveStreamCommand.GetParameter(14).Value = stream.IsForced; + _saveStreamCommand.GetParameter(15).Value = stream.IsExternal; + + _saveStreamCommand.GetParameter(16).Value = stream.Width; + _saveStreamCommand.GetParameter(17).Value = stream.Height; + _saveStreamCommand.GetParameter(18).Value = stream.AverageFrameRate; + _saveStreamCommand.GetParameter(19).Value = stream.RealFrameRate; + _saveStreamCommand.GetParameter(20).Value = stream.Level; + + _saveStreamCommand.Transaction = transaction; + _saveStreamCommand.ExecuteNonQuery(); + } + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + catch (Exception e) + { + _logger.ErrorException("Failed to save media streams:", e); + + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + + _writeLock.Release(); + } + } + + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private readonly object _disposeLock = new object(); + + /// <summary> + /// Releases unmanaged and - optionally - managed resources. + /// </summary> + /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + try + { + lock (_disposeLock) + { + if (_connection != null) + { + if (_connection.IsOpen()) + { + _connection.Close(); + } + + _connection.Dispose(); + _connection = null; + } + } + } + catch (Exception ex) + { + _logger.ErrorException("Error disposing database", ex); + } + } + } + } +} + diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs new file mode 100644 index 000000000..c704808f3 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs @@ -0,0 +1,265 @@ +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Persistence +{ + class SqliteProviderInfoRepository + { + private IDbConnection _connection; + + private readonly ILogger _logger; + + private IDbCommand _deleteInfosCommand; + private IDbCommand _saveInfoCommand; + + public SqliteProviderInfoRepository(IDbConnection connection, ILogManager logManager) + { + _connection = connection; + + _logger = logManager.GetLogger(GetType().Name); + } + + /// <summary> + /// Opens the connection to the database + /// </summary> + /// <returns>Task.</returns> + public void Initialize() + { + var createTableCommand + = "create table if not exists providerinfos "; + + createTableCommand += "(ItemId GUID, ProviderId GUID, ProviderVersion TEXT, FileStamp GUID, LastRefreshStatus TEXT, LastRefreshed datetime, PRIMARY KEY (ItemId, ProviderId))"; + + string[] queries = { + + createTableCommand, + "create index if not exists idx_providerinfos on providerinfos(ItemId, ProviderId)", + + //pragmas + "pragma temp_store = memory" + }; + + _connection.RunQueries(queries, _logger); + + PrepareStatements(); + } + + private static readonly string[] SaveColumns = + { + "ItemId", + "ProviderId", + "ProviderVersion", + "FileStamp", + "LastRefreshStatus", + "LastRefreshed" + }; + + private readonly string[] _selectColumns = SaveColumns.Skip(1).ToArray(); + + /// <summary> + /// The _write lock + /// </summary> + private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1); + + /// <summary> + /// Prepares the statements. + /// </summary> + private void PrepareStatements() + { + _deleteInfosCommand = _connection.CreateCommand(); + _deleteInfosCommand.CommandText = "delete from providerinfos where ItemId=@ItemId"; + _deleteInfosCommand.Parameters.Add(_deleteInfosCommand, "@ItemId"); + + _saveInfoCommand = _connection.CreateCommand(); + + _saveInfoCommand.CommandText = string.Format("replace into providerinfos ({0}) values ({1})", + string.Join(",", SaveColumns), + string.Join(",", SaveColumns.Select(i => "@" + i).ToArray())); + + foreach (var col in SaveColumns) + { + _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@" + col); + } + } + + public IEnumerable<BaseProviderInfo> GetBaseProviderInfos(Guid itemId) + { + if (itemId == Guid.Empty) + { + throw new ArgumentNullException("itemId"); + } + + using (var cmd = _connection.CreateCommand()) + { + var cmdText = "select " + string.Join(",", _selectColumns) + " from providerinfos where"; + + cmdText += " ItemId=@ItemId"; + cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = itemId; + + cmd.CommandText = cmdText; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + yield return GetBaseProviderInfo(reader); + } + } + } + } + + /// <summary> + /// Gets the chapter. + /// </summary> + /// <param name="reader">The reader.</param> + /// <returns>ChapterInfo.</returns> + private BaseProviderInfo GetBaseProviderInfo(IDataReader reader) + { + var item = new BaseProviderInfo + { + ProviderId = reader.GetGuid(0) + }; + + if (!reader.IsDBNull(1)) + { + item.ProviderVersion = reader.GetString(1); + } + + item.FileStamp = reader.GetGuid(2); + item.LastRefreshStatus = (ProviderRefreshStatus)Enum.Parse(typeof(ProviderRefreshStatus), reader.GetString(3), true); + item.LastRefreshed = reader.GetDateTime(4).ToUniversalTime(); + + return item; + } + + public async Task SaveProviderInfos(Guid id, IEnumerable<BaseProviderInfo> infos, CancellationToken cancellationToken) + { + if (id == Guid.Empty) + { + throw new ArgumentNullException("id"); + } + + if (infos == null) + { + throw new ArgumentNullException("infos"); + } + + cancellationToken.ThrowIfCancellationRequested(); + + await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + IDbTransaction transaction = null; + + try + { + transaction = _connection.BeginTransaction(); + + // First delete chapters + _deleteInfosCommand.GetParameter(0).Value = id; + + _deleteInfosCommand.Transaction = transaction; + + _deleteInfosCommand.ExecuteNonQuery(); + + foreach (var stream in infos) + { + if (stream.LastRefreshed == DateTime.MinValue) + { + throw new Exception("LastRefreshed still has DateTime.MinValue"); + + } + cancellationToken.ThrowIfCancellationRequested(); + + _saveInfoCommand.GetParameter(0).Value = id; + _saveInfoCommand.GetParameter(1).Value = stream.ProviderId; + _saveInfoCommand.GetParameter(2).Value = stream.ProviderVersion; + _saveInfoCommand.GetParameter(3).Value = stream.FileStamp; + _saveInfoCommand.GetParameter(4).Value = stream.LastRefreshStatus.ToString(); + _saveInfoCommand.GetParameter(5).Value = stream.LastRefreshed; + + _saveInfoCommand.Transaction = transaction; + _saveInfoCommand.ExecuteNonQuery(); + } + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + catch (Exception e) + { + _logger.ErrorException("Failed to save provider info:", e); + + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + + _writeLock.Release(); + } + } + + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private readonly object _disposeLock = new object(); + + /// <summary> + /// Releases unmanaged and - optionally - managed resources. + /// </summary> + /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + try + { + lock (_disposeLock) + { + if (_connection != null) + { + if (_connection.IsOpen()) + { + _connection.Close(); + } + + _connection.Dispose(); + _connection = null; + } + } + } + catch (Exception ex) + { + _logger.ErrorException("Error disposing database", ex); + } + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs index a9d5d8746..fa195859b 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs @@ -31,36 +31,26 @@ namespace MediaBrowser.Server.Implementations.Persistence } } - private readonly IJsonSerializer _jsonSerializer; - /// <summary> /// The _app paths /// </summary> private readonly IApplicationPaths _appPaths; /// <summary> - /// Initializes a new instance of the <see cref="SqliteUserDataRepository"/> class. + /// Initializes a new instance of the <see cref="SqliteUserDataRepository" /> class. /// </summary> /// <param name="appPaths">The app paths.</param> - /// <param name="jsonSerializer">The json serializer.</param> /// <param name="logManager">The log manager.</param> - /// <exception cref="System.ArgumentNullException"> - /// jsonSerializer + /// <exception cref="System.ArgumentNullException">jsonSerializer /// or - /// appPaths - /// </exception> - public SqliteUserDataRepository(IApplicationPaths appPaths, IJsonSerializer jsonSerializer, ILogManager logManager) + /// appPaths</exception> + public SqliteUserDataRepository(IApplicationPaths appPaths, ILogManager logManager) { - if (jsonSerializer == null) - { - throw new ArgumentNullException("jsonSerializer"); - } if (appPaths == null) { throw new ArgumentNullException("appPaths"); } - _jsonSerializer = jsonSerializer; _appPaths = appPaths; _logger = logManager.GetLogger(GetType().Name); } @@ -243,7 +233,7 @@ namespace MediaBrowser.Server.Implementations.Persistence if (!reader.IsDBNull(5)) { - userData.LastPlayedDate = reader.GetDateTime(5); + userData.LastPlayedDate = reader.GetDateTime(5).ToUniversalTime(); } } } diff --git a/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs b/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs index 7b2a038f4..511092759 100644 --- a/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs +++ b/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; @@ -52,6 +53,8 @@ namespace MediaBrowser.Server.Implementations.Providers private IImageProvider[] ImageProviders { get; set; } private readonly IFileSystem _fileSystem; + private readonly IItemRepository _itemRepo; + /// <summary> /// Initializes a new instance of the <see cref="ProviderManager" /> class. /// </summary> @@ -59,13 +62,14 @@ namespace MediaBrowser.Server.Implementations.Providers /// <param name="configurationManager">The configuration manager.</param> /// <param name="directoryWatchers">The directory watchers.</param> /// <param name="logManager">The log manager.</param> - public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, IDirectoryWatchers directoryWatchers, ILogManager logManager, IFileSystem fileSystem) + public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, IDirectoryWatchers directoryWatchers, ILogManager logManager, IFileSystem fileSystem, IItemRepository itemRepo) { _logger = logManager.GetLogger("ProviderManager"); _httpClient = httpClient; ConfigurationManager = configurationManager; _directoryWatchers = directoryWatchers; _fileSystem = fileSystem; + _itemRepo = itemRepo; } /// <summary> @@ -102,6 +106,10 @@ namespace MediaBrowser.Server.Implementations.Providers var enableInternetProviders = ConfigurationManager.Configuration.EnableInternetProviders; var excludeTypes = ConfigurationManager.Configuration.InternetProviderExcludeTypes; + var providerHistories = item.DateLastSaved == DateTime.MinValue ? + new List<BaseProviderInfo>() : + _itemRepo.GetProviderHistory(item.Id).ToList(); + // Run the normal providers sequentially in order of priority foreach (var provider in MetadataProviders) { @@ -140,9 +148,20 @@ namespace MediaBrowser.Server.Implementations.Providers continue; } + var providerInfo = providerHistories.FirstOrDefault(i => i.ProviderId == provider.Id); + + if (providerInfo == null) + { + providerInfo = new BaseProviderInfo + { + ProviderId = provider.Id + }; + providerHistories.Add(providerInfo); + } + try { - if (!force && !provider.NeedsRefresh(item)) + if (!force && !provider.NeedsRefresh(item, providerInfo)) { continue; } @@ -152,7 +171,7 @@ namespace MediaBrowser.Server.Implementations.Providers _logger.Error("Error determining NeedsRefresh for {0}", ex, item.Path); } - var updateType = await FetchAsync(provider, item, force, cancellationToken).ConfigureAwait(false); + var updateType = await FetchAsync(provider, item, providerInfo, force, cancellationToken).ConfigureAwait(false); if (updateType.HasValue) { @@ -167,6 +186,11 @@ namespace MediaBrowser.Server.Implementations.Providers } } + if (result.HasValue || force) + { + await _itemRepo.SaveProviderHistory(item.Id, providerHistories, cancellationToken); + } + return result; } @@ -194,15 +218,16 @@ namespace MediaBrowser.Server.Implementations.Providers /// </summary> /// <param name="provider">The provider.</param> /// <param name="item">The item.</param> + /// <param name="providerInfo">The provider information.</param> /// <param name="force">if set to <c>true</c> [force].</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{System.Boolean}.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - private async Task<ItemUpdateType?> FetchAsync(BaseMetadataProvider provider, BaseItem item, bool force, CancellationToken cancellationToken) + /// <exception cref="System.ArgumentNullException">item</exception> + private async Task<ItemUpdateType?> FetchAsync(BaseMetadataProvider provider, BaseItem item, BaseProviderInfo providerInfo, bool force, CancellationToken cancellationToken) { if (item == null) { - throw new ArgumentNullException(); + throw new ArgumentNullException("item"); } cancellationToken.ThrowIfCancellationRequested(); @@ -213,12 +238,9 @@ namespace MediaBrowser.Server.Implementations.Providers _logger.Debug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name ?? "--Unknown--"); } - // This provides the ability to cancel just this one provider - var innerCancellationTokenSource = new CancellationTokenSource(); - try { - var changed = await provider.FetchAsync(item, force, CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token).ConfigureAwait(false); + var changed = await provider.FetchAsync(item, force, providerInfo, cancellationToken).ConfigureAwait(false); if (changed) { @@ -243,14 +265,10 @@ namespace MediaBrowser.Server.Implementations.Providers { _logger.ErrorException("{0} failed refreshing {1} {2}", ex, provider.GetType().Name, item.Name, item.Path ?? string.Empty); - provider.SetLastRefreshed(item, DateTime.UtcNow, ProviderRefreshStatus.Failure); + provider.SetLastRefreshed(item, DateTime.UtcNow, providerInfo, ProviderRefreshStatus.Failure); return ItemUpdateType.Unspecified; } - finally - { - innerCancellationTokenSource.Dispose(); - } } /// <summary> diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs index c82899948..9270b879a 100644 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs +++ b/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs @@ -101,7 +101,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks // Limit to video files to reduce changes of ffmpeg crash dialog foreach (var item in newItems - .Where(i => i.LocationType == LocationType.FileSystem && i.VideoType == VideoType.VideoFile && string.IsNullOrEmpty(i.PrimaryImagePath) && i.MediaStreams.Any(m => m.Type == MediaStreamType.Video)) + .Where(i => i.LocationType == LocationType.FileSystem && i.VideoType == VideoType.VideoFile && string.IsNullOrEmpty(i.PrimaryImagePath) && i.DefaultVideoStreamIndex.HasValue) .Take(2)) { try diff --git a/MediaBrowser.Server.Implementations/Sorting/VideoBitRateComparer.cs b/MediaBrowser.Server.Implementations/Sorting/VideoBitRateComparer.cs index 469eb5d6a..cbf6ebac6 100644 --- a/MediaBrowser.Server.Implementations/Sorting/VideoBitRateComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/VideoBitRateComparer.cs @@ -1,8 +1,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; -using System.Linq; namespace MediaBrowser.Server.Implementations.Sorting { @@ -21,17 +19,11 @@ namespace MediaBrowser.Server.Implementations.Sorting private int GetValue(BaseItem item) { - var video = item as IHasMediaStreams; + var video = item as Video; if (video != null) { - var videoStream = video.MediaStreams - .FirstOrDefault(i => i.Type == MediaStreamType.Video); - - if (videoStream != null) - { - return videoStream.BitRate ?? 0; - } + return video.VideoBitRate ?? 0; } return 0; diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index 8fd4b2b0d..be7fb7b27 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -32,6 +32,11 @@ <PlatformTarget>x86</PlatformTarget> <Externalconsole>true</Externalconsole> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <Optimize>false</Optimize> + <OutputPath>bin\Release</OutputPath> + <WarningLevel>4</WarningLevel> + </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="ServiceStack.Common"> diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index ac6959e45..39871df66 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -269,7 +269,7 @@ namespace MediaBrowser.ServerApplication DirectoryWatchers = new DirectoryWatchers(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager); RegisterSingleInstance(DirectoryWatchers); - ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, DirectoryWatchers, LogManager, FileSystemManager); + ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, DirectoryWatchers, LogManager, FileSystemManager, ItemRepository); RegisterSingleInstance(ProviderManager); RegisterSingleInstance<ILibrarySearchEngine>(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager)); @@ -394,7 +394,7 @@ namespace MediaBrowser.ServerApplication /// <returns>Task.</returns> private async Task ConfigureUserDataRepositories() { - var repo = new SqliteUserDataRepository(ApplicationPaths, JsonSerializer, LogManager); + var repo = new SqliteUserDataRepository(ApplicationPaths, LogManager); await repo.Initialize().ConfigureAwait(false); diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs index 87a70f534..ec7dc582d 100644 --- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs @@ -3,7 +3,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg { public static class FFMpegDownloadInfo { - public static string Version = "ffmpeg20131110"; + public static string Version = "ffmpeg20131110.1"; public static string[] FfMpegUrls = new[] { |
