From 28ffeb5121247ced3fc7d764242e41b92837f740 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 26 Feb 2015 15:06:42 -0500 Subject: sync updates --- .../MediaBrowser.Server.Implementations.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj') diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 509a274ee..5ceaa5f5b 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -47,7 +47,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.2\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.3\lib\net45\ImageMagickSharp.dll False -- cgit v1.2.3 From 2bf2d5fd769788cade10a84fc7a4a4af23c23cf1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 28 Feb 2015 08:42:47 -0500 Subject: cloud sync updates --- MediaBrowser.Api/Images/ImageService.cs | 2 +- MediaBrowser.Api/Playback/TranscodingThrottler.cs | 50 ++--- MediaBrowser.Controller/Drawing/IImageProcessor.cs | 6 +- .../MediaBrowser.Controller.csproj | 2 +- MediaBrowser.Controller/Sync/ICloudSyncProvider.cs | 46 ---- .../Sync/IServerSyncProvider.cs | 54 ++++- MediaBrowser.Controller/Sync/ISyncDataProvider.cs | 41 ++++ MediaBrowser.Controller/Sync/ISyncProvider.cs | 7 - MediaBrowser.Dlna/Didl/DidlBuilder.cs | 2 +- MediaBrowser.Model/Users/UserPolicy.cs | 2 + MediaBrowser.Providers/Photos/PhotoProvider.cs | 2 +- .../Drawing/ImageProcessor.cs | 7 +- .../Dto/DtoService.cs | 5 +- .../Localization/Server/server.json | 6 +- .../MediaBrowser.Server.Implementations.csproj | 6 +- .../Sync/AppSyncProvider.cs | 2 +- .../Sync/CloudSyncProfile.cs | 118 ++++++++++ .../Sync/CloudSyncProvider.cs | 57 ----- .../Sync/FolderSync/FolderSyncDataProvider.cs | 31 +++ .../Sync/FolderSync/FolderSyncProvider.cs | 142 ++++++++++++ .../Sync/IHasSyncProfile.cs | 15 ++ .../Sync/MediaSync.cs | 249 ++++++++++++++++++--- .../Sync/MultiProviderSync.cs | 69 ++++++ .../Sync/SyncManager.cs | 21 +- 24 files changed, 732 insertions(+), 210 deletions(-) delete mode 100644 MediaBrowser.Controller/Sync/ICloudSyncProvider.cs create mode 100644 MediaBrowser.Controller/Sync/ISyncDataProvider.cs create mode 100644 MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs delete mode 100644 MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs create mode 100644 MediaBrowser.Server.Implementations/Sync/FolderSync/FolderSyncDataProvider.cs create mode 100644 MediaBrowser.Server.Implementations/Sync/FolderSync/FolderSyncProvider.cs create mode 100644 MediaBrowser.Server.Implementations/Sync/IHasSyncProfile.cs create mode 100644 MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs (limited to 'MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj') diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index e29bbf674..0a39b51c3 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -318,7 +318,7 @@ namespace MediaBrowser.Api.Images try { - var size = _imageProcessor.GetImageSize(info.Path, info.DateModified); + var size = _imageProcessor.GetImageSize(info); width = Convert.ToInt32(size.Width); height = Convert.ToInt32(size.Height); diff --git a/MediaBrowser.Api/Playback/TranscodingThrottler.cs b/MediaBrowser.Api/Playback/TranscodingThrottler.cs index 81848c017..50c213655 100644 --- a/MediaBrowser.Api/Playback/TranscodingThrottler.cs +++ b/MediaBrowser.Api/Playback/TranscodingThrottler.cs @@ -13,11 +13,17 @@ namespace MediaBrowser.Api.Playback public void Start() { - _timer = new Timer(TimerCallback, null, 1000, 1000); + _timer = new Timer(TimerCallback, null, 5000, 5000); } private void TimerCallback(object state) { + if (_job.HasExited) + { + DisposeTimer(); + return; + } + if (IsThrottleAllowed(_job)) { PauseTranscoding(); @@ -50,36 +56,6 @@ namespace MediaBrowser.Api.Playback private bool IsThrottleAllowed(TranscodingJob job) { - //var job = string.IsNullOrEmpty(request.TranscodingJobId) ? - //null : - //ApiEntryPoint.Instance.GetTranscodingJob(request.TranscodingJobId); - - //var limits = new List(); - //if (state.InputBitrate.HasValue) - //{ - // // Bytes per second - // limits.Add((state.InputBitrate.Value / 8)); - //} - //if (state.InputFileSize.HasValue && state.RunTimeTicks.HasValue) - //{ - // var totalSeconds = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalSeconds; - - // if (totalSeconds > 1) - // { - // var timeBasedLimit = state.InputFileSize.Value / totalSeconds; - // limits.Add(Convert.ToInt64(timeBasedLimit)); - // } - //} - - //// Take the greater of the above to methods, just to be safe - //var throttleLimit = limits.Count > 0 ? limits.First() : 0; - - //// Pad to play it safe - //var bytesPerSecond = Convert.ToInt64(1.05 * throttleLimit); - - //// Don't even start evaluating this until at least two minutes have content have been consumed - //var targetGap = throttleLimit * 120; - var bytesDownloaded = job.BytesDownloaded ?? 0; var transcodingPositionTicks = job.TranscodingPositionTicks ?? 0; var downloadPositionTicks = job.DownloadPositionTicks ?? 0; @@ -95,11 +71,11 @@ namespace MediaBrowser.Api.Playback if (gap < targetGap) { - //Logger.Debug("Not throttling transcoder gap {0} target gap {1}", gap, targetGap); + //_logger.Debug("Not throttling transcoder gap {0} target gap {1}", gap, targetGap); return false; } - //Logger.Debug("Throttling transcoder gap {0} target gap {1}", gap, targetGap); + //_logger.Debug("Throttling transcoder gap {0} target gap {1}", gap, targetGap); return true; } @@ -120,21 +96,21 @@ namespace MediaBrowser.Api.Playback if (gap < targetGap) { - //Logger.Debug("Not throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); + //_logger.Debug("Not throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); return false; } - //Logger.Debug("Throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); + //_logger.Debug("Throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); return true; } catch { - //Logger.Error("Error getting output size"); + //_logger.Error("Error getting output size"); } } else { - //Logger.Debug("No throttle data for " + path); + //_logger.Debug("No throttle data for " + path); } return false; diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 8ac7d56d2..6fafc2b46 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -2,7 +2,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; -using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -30,10 +29,9 @@ namespace MediaBrowser.Controller.Drawing /// /// Gets the size of the image. /// - /// The path. - /// The image date modified. + /// The information. /// ImageSize. - ImageSize GetImageSize(string path, DateTime imageDateModified); + ImageSize GetImageSize(ItemImageInfo info); /// /// Adds the parts. diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index e9531e057..603cb02e0 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -341,8 +341,8 @@ - + diff --git a/MediaBrowser.Controller/Sync/ICloudSyncProvider.cs b/MediaBrowser.Controller/Sync/ICloudSyncProvider.cs deleted file mode 100644 index 8f03aea0a..000000000 --- a/MediaBrowser.Controller/Sync/ICloudSyncProvider.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediaBrowser.Model.Sync; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Sync -{ - public interface ICloudSyncProvider - { - /// - /// Gets the name. - /// - /// The name. - string Name { get; } - - /// - /// Gets the synchronize targets. - /// - /// The user identifier. - /// IEnumerable<SyncTarget>. - IEnumerable GetSyncTargets(string userId); - - /// - /// Transfers the item file. - /// - /// The input file. - /// The path parts. - /// The target. - /// The progress. - /// The cancellation token. - /// Task. - Task SendFile(string inputFile, string[] pathParts, SyncTarget target, IProgress progress, CancellationToken cancellationToken); - - /// - /// Gets the file. - /// - /// The path parts. - /// The target. - /// The progress. - /// The cancellation token. - /// Task<Stream>. - Task GetFile(string[] pathParts, SyncTarget target, IProgress progress, CancellationToken cancellationToken); - } -} diff --git a/MediaBrowser.Controller/Sync/IServerSyncProvider.cs b/MediaBrowser.Controller/Sync/IServerSyncProvider.cs index b3e74ee7d..9ee83acbf 100644 --- a/MediaBrowser.Controller/Sync/IServerSyncProvider.cs +++ b/MediaBrowser.Controller/Sync/IServerSyncProvider.cs @@ -1,5 +1,6 @@ using MediaBrowser.Model.Sync; using System; +using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -12,21 +13,66 @@ namespace MediaBrowser.Controller.Sync /// Transfers the file. /// /// The input file. - /// The path parts. + /// The path. /// The target. /// The progress. /// The cancellation token. /// Task. - Task SendFile(string inputFile, string[] pathParts, SyncTarget target, IProgress progress, CancellationToken cancellationToken); + Task SendFile(string inputFile, string path, SyncTarget target, IProgress progress, CancellationToken cancellationToken); + + /// + /// Deletes the file. + /// + /// The path. + /// The target. + /// The cancellation token. + /// Task. + Task DeleteFile(string path, SyncTarget target, CancellationToken cancellationToken); /// /// Gets the file. /// - /// The path parts. + /// The path. /// The target. /// The progress. /// The cancellation token. /// Task<Stream>. - Task GetFile(string[] pathParts, SyncTarget target, IProgress progress, CancellationToken cancellationToken); + Task GetFile(string path, SyncTarget target, IProgress progress, CancellationToken cancellationToken); + + /// + /// Gets the full path. + /// + /// The path. + /// The target. + /// System.String. + string GetFullPath(IEnumerable path, SyncTarget target); + + /// + /// Gets the parent directory path. + /// + /// The path. + /// The target. + /// System.String. + string GetParentDirectoryPath(string path, SyncTarget target); + + /// + /// Gets the file system entries. + /// + /// The path. + /// The target. + /// Task<List<DeviceFileInfo>>. + Task> GetFileSystemEntries(string path, SyncTarget target); + + /// + /// Gets the data provider. + /// + /// ISyncDataProvider. + ISyncDataProvider GetDataProvider(); + + /// + /// Gets all synchronize targets. + /// + /// IEnumerable<SyncTarget>. + IEnumerable GetAllSyncTargets(); } } diff --git a/MediaBrowser.Controller/Sync/ISyncDataProvider.cs b/MediaBrowser.Controller/Sync/ISyncDataProvider.cs new file mode 100644 index 000000000..cf698dd3c --- /dev/null +++ b/MediaBrowser.Controller/Sync/ISyncDataProvider.cs @@ -0,0 +1,41 @@ +using MediaBrowser.Model.Sync; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Sync +{ + public interface ISyncDataProvider + { + /// + /// Gets the server item ids. + /// + /// The target. + /// The server identifier. + /// Task<List<System.String>>. + Task> GetServerItemIds(SyncTarget target, string serverId); + + /// + /// Adds the or update. + /// + /// The target. + /// The item. + /// Task. + Task AddOrUpdate(SyncTarget target, LocalItem item); + + /// + /// Deletes the specified identifier. + /// + /// The target. + /// The identifier. + /// Task. + Task Delete(SyncTarget target, string id); + + /// + /// Gets the specified identifier. + /// + /// The target. + /// The identifier. + /// Task<LocalItem>. + Task Get(SyncTarget target, string id); + } +} diff --git a/MediaBrowser.Controller/Sync/ISyncProvider.cs b/MediaBrowser.Controller/Sync/ISyncProvider.cs index 6f24eac1a..ba6e54d45 100644 --- a/MediaBrowser.Controller/Sync/ISyncProvider.cs +++ b/MediaBrowser.Controller/Sync/ISyncProvider.cs @@ -18,13 +18,6 @@ namespace MediaBrowser.Controller.Sync /// The user identifier. /// IEnumerable<SyncTarget>. IEnumerable GetSyncTargets(string userId); - - /// - /// Gets the device profile. - /// - /// The target. - /// DeviceProfile. - DeviceProfile GetDeviceProfile(SyncTarget target); } public interface IHasUniqueTargetIds diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index af7c8dbed..b2eedad7c 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -930,7 +930,7 @@ namespace MediaBrowser.Dlna.Didl try { - var size = _imageProcessor.GetImageSize(imageInfo.Path, imageInfo.DateModified); + var size = _imageProcessor.GetImageSize(imageInfo); width = Convert.ToInt32(size.Width); height = Convert.ToInt32(size.Height); diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index 410cdc51f..7efc2cf6f 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -59,6 +59,8 @@ namespace MediaBrowser.Model.Users public string[] EnabledFolders { get; set; } public bool EnableAllFolders { get; set; } + public int InvalidLoginAttemptCount { get; set; } + public UserPolicy() { EnableLiveTvManagement = true; diff --git a/MediaBrowser.Providers/Photos/PhotoProvider.cs b/MediaBrowser.Providers/Photos/PhotoProvider.cs index 3eaef59fb..96160dcc4 100644 --- a/MediaBrowser.Providers/Photos/PhotoProvider.cs +++ b/MediaBrowser.Providers/Photos/PhotoProvider.cs @@ -146,7 +146,7 @@ namespace MediaBrowser.Providers.Photos try { - var size = _imageProcessor.GetImageSize(imageInfo.Path, imageInfo.DateModified); + var size = _imageProcessor.GetImageSize(imageInfo); item.Width = Convert.ToInt32(size.Width); item.Height = Convert.ToInt32(size.Height); diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs index 85eadd73c..c484a60db 100644 --- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs +++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs @@ -414,6 +414,11 @@ namespace MediaBrowser.Server.Implementations.Drawing return GetImageSize(path, File.GetLastWriteTimeUtc(path)); } + public ImageSize GetImageSize(ItemImageInfo info) + { + return GetImageSize(info.Path, info.DateModified); + } + /// /// Gets the size of the image. /// @@ -421,7 +426,7 @@ namespace MediaBrowser.Server.Implementations.Drawing /// The image date modified. /// ImageSize. /// path - public ImageSize GetImageSize(string path, DateTime imageDateModified) + private ImageSize GetImageSize(string path, DateTime imageDateModified) { if (string.IsNullOrEmpty(path)) { diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index b15809738..75037159c 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1598,14 +1598,11 @@ namespace MediaBrowser.Server.Implementations.Dto var path = imageInfo.Path; - // See if we can avoid a file system lookup by looking for the file in ResolveArgs - var dateModified = imageInfo.DateModified; - ImageSize size; try { - size = _imageProcessor.GetImageSize(path, dateModified); + size = _imageProcessor.GetImageSize(imageInfo); } catch (FileNotFoundException) { diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index dc80778da..5f221a7be 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -1114,7 +1114,7 @@ "MessageApplicationUpdated": "Media Browser Server has been updated", "AuthenticationSucceededWithUserName": "{0} successfully authenticated", "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", + "UserDownloadingItemWithValues": "{0} is downloading {1}", "UserStartedPlayingItemWithValues": "{0} has started playing {1}", "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", "AppDeviceValues": "App: {0}, Device: {1}", @@ -1369,5 +1369,7 @@ "TabJobs": "Jobs", "TabSyncJobs": "Sync Jobs", "LabelTagFilterMode": "Mode:", - "LabelTagFilterAllowModeHelp": "If allowed tags are used as part of a deeply nested folder structure, content that is tagged will require parent folders to be tagged as well." + "LabelTagFilterAllowModeHelp": "If allowed tags are used as part of a deeply nested folder structure, content that is tagged will require parent folders to be tagged as well.", + "HeaderThisUserIsCurrentlyDisabled": "This user is currently disabled", + "MessageReenableUser": "See below to reenable" } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 5ceaa5f5b..40aaa299f 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -303,8 +303,12 @@ - + + + + + diff --git a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs index d35ff8fc4..29ac74e82 100644 --- a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs +++ b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs @@ -8,7 +8,7 @@ using System.Linq; namespace MediaBrowser.Server.Implementations.Sync { - public class AppSyncProvider : ISyncProvider, IHasUniqueTargetIds + public class AppSyncProvider : ISyncProvider, IHasUniqueTargetIds, IHasSyncProfile { private readonly IDeviceManager _deviceManager; diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs new file mode 100644 index 000000000..babdf3f80 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs @@ -0,0 +1,118 @@ +using MediaBrowser.Model.Dlna; + +namespace MediaBrowser.Server.Implementations.Sync +{ + public class CloudSyncProfile : DeviceProfile + { + public CloudSyncProfile(bool supportsAc3, bool supportsDca) + { + Name = "Cloud Sync"; + + MaxStreamingBitrate = 20000000; + MaxStaticBitrate = 20000000; + + var mkvAudio = "aac,mp3"; + var mp4Audio = "aac"; + + if (supportsAc3) + { + mkvAudio += ",ac3"; + mp4Audio += ",ac3"; + } + + if (supportsDca) + { + mkvAudio += ",dca"; + } + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Container = "mkv", + VideoCodec = "h264,mpeg4", + AudioCodec = mkvAudio, + Type = DlnaProfileType.Video + }, + new DirectPlayProfile + { + Container = "mp4,mov,m4v", + VideoCodec = "h264,mpeg4", + AudioCodec = mp4Audio, + Type = DlnaProfileType.Video + } + }; + + ContainerProfiles = new ContainerProfile[] { }; + + CodecProfiles = new[] + { + new CodecProfile + { + Type = CodecType.Video, + Conditions = new [] + { + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.VideoBitDepth, + Value = "8", + IsRequired = false + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Height, + Value = "1080", + IsRequired = false + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.RefFrames, + Value = "12", + IsRequired = false + } + } + } + }; + + SubtitleProfiles = new[] + { + new SubtitleProfile + { + Format = "srt", + Method = SubtitleDeliveryMethod.External + } + }; + + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + AudioCodec = "mp3", + Type = DlnaProfileType.Audio, + Context = EncodingContext.Static + }, + + new TranscodingProfile + { + Container = "mp4", + Type = DlnaProfileType.Video, + AudioCodec = "aac", + VideoCodec = "h264", + Context = EncodingContext.Static + }, + + new TranscodingProfile + { + Container = "jpeg", + Type = DlnaProfileType.Photo, + Context = EncodingContext.Static + } + }; + + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs deleted file mode 100644 index 1ef9d4b15..000000000 --- a/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Sync; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class CloudSyncProvider : IServerSyncProvider - { - private readonly ICloudSyncProvider[] _providers = {}; - - public CloudSyncProvider(IApplicationHost appHost) - { - _providers = appHost.GetExports().ToArray(); - } - - public IEnumerable GetSyncTargets(string userId) - { - return _providers.SelectMany(i => i.GetSyncTargets(userId)); - } - - public DeviceProfile GetDeviceProfile(SyncTarget target) - { - return new DeviceProfile(); - } - - public string Name - { - get { return "Cloud Sync"; } - } - - private ICloudSyncProvider GetProvider(SyncTarget target) - { - return null; - } - - public Task SendFile(string inputFile, string[] pathParts, SyncTarget target, IProgress progress, CancellationToken cancellationToken) - { - var provider = GetProvider(target); - - return provider.SendFile(inputFile, pathParts, target, progress, cancellationToken); - } - - public Task GetFile(string[] pathParts, SyncTarget target, IProgress progress, CancellationToken cancellationToken) - { - var provider = GetProvider(target); - - return provider.GetFile(pathParts, target, progress, cancellationToken); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/FolderSync/FolderSyncDataProvider.cs b/MediaBrowser.Server.Implementations/Sync/FolderSync/FolderSyncDataProvider.cs new file mode 100644 index 000000000..b9008d87e --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/FolderSync/FolderSyncDataProvider.cs @@ -0,0 +1,31 @@ +using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Sync; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Sync.FolderSync +{ + public class FolderSyncDataProvider : ISyncDataProvider + { + public Task> GetServerItemIds(SyncTarget target, string serverId) + { + throw new NotImplementedException(); + } + + public Task AddOrUpdate(SyncTarget target, LocalItem item) + { + throw new NotImplementedException(); + } + + public Task Delete(SyncTarget target, string id) + { + throw new NotImplementedException(); + } + + public Task Get(SyncTarget target, string id) + { + throw new NotImplementedException(); + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sync/FolderSync/FolderSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/FolderSync/FolderSyncProvider.cs new file mode 100644 index 000000000..9cf234106 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/FolderSync/FolderSyncProvider.cs @@ -0,0 +1,142 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Sync; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Sync.FolderSync +{ + public class FolderSyncProvider : IServerSyncProvider + { + private readonly IApplicationPaths _appPaths; + private readonly IUserManager _userManager; + + public FolderSyncProvider(IApplicationPaths appPaths, IUserManager userManager) + { + _appPaths = appPaths; + _userManager = userManager; + } + + public Task SendFile(string inputFile, string path, SyncTarget target, IProgress progress, CancellationToken cancellationToken) + { + return Task.Run(() => File.Copy(inputFile, path, true), cancellationToken); + } + + public Task DeleteFile(string path, SyncTarget target, CancellationToken cancellationToken) + { + return Task.Run(() => File.Delete(path), cancellationToken); + } + + public Task GetFile(string path, SyncTarget target, IProgress progress, CancellationToken cancellationToken) + { + return Task.FromResult((Stream)File.OpenRead(path)); + } + + public string GetFullPath(IEnumerable paths, SyncTarget target) + { + var account = GetSyncAccounts() + .FirstOrDefault(i => string.Equals(i.Id, target.Id, StringComparison.OrdinalIgnoreCase)); + + if (account == null) + { + throw new ArgumentException("Invalid SyncTarget supplied."); + } + + var list = paths.ToList(); + list.Insert(0, account.Path); + + return Path.Combine(list.ToArray()); + } + + public string GetParentDirectoryPath(string path, SyncTarget target) + { + return Path.GetDirectoryName(path); + } + + public Task> GetFileSystemEntries(string path, SyncTarget target) + { + List files; + + try + { + files = new DirectoryInfo(path).EnumerateFiles("*", SearchOption.TopDirectoryOnly).ToList(); + } + catch (DirectoryNotFoundException) + { + files = new List(); + } + + return Task.FromResult(files.Select(i => new DeviceFileInfo + { + Name = i.Name, + Path = i.FullName + + }).ToList()); + } + + public ISyncDataProvider GetDataProvider() + { + // If single instances are needed, manage them here + return new FolderSyncDataProvider(); + } + + public string Name + { + get { return "Folder Sync"; } + } + + public IEnumerable GetSyncTargets(string userId) + { + return GetSyncAccounts() + .Where(i => i.UserIds.Contains(userId, StringComparer.OrdinalIgnoreCase)) + .Select(GetSyncTarget); + } + + public IEnumerable GetAllSyncTargets() + { + return GetSyncAccounts().Select(GetSyncTarget); + } + + private SyncTarget GetSyncTarget(SyncAccount account) + { + return new SyncTarget + { + Id = account.Id, + Name = account.Name + }; + } + + private IEnumerable GetSyncAccounts() + { + // Dummy this up + return _userManager + .Users + .Select(i => new SyncAccount + { + Id = i.Id.ToString("N"), + UserIds = new List { i.Id.ToString("N") }, + Path = Path.Combine(_appPaths.DataPath, "foldersync", i.Id.ToString("N")), + Name = i.Name + "'s Folder Sync" + }); + } + + // An internal class to manage all configured Folder Sync accounts for differnet users + class SyncAccount + { + public string Id { get; set; } + public string Name { get; set; } + public string Path { get; set; } + public List UserIds { get; set; } + + public SyncAccount() + { + UserIds = new List(); + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sync/IHasSyncProfile.cs b/MediaBrowser.Server.Implementations/Sync/IHasSyncProfile.cs new file mode 100644 index 000000000..b7e9daf49 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/IHasSyncProfile.cs @@ -0,0 +1,15 @@ +using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Sync; + +namespace MediaBrowser.Server.Implementations.Sync +{ + public interface IHasSyncProfile + { + /// + /// Gets the device profile. + /// + /// The target. + /// DeviceProfile. + DeviceProfile GetDeviceProfile(SyncTarget target); + } +} diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs index 764652bbf..0407510a8 100644 --- a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs +++ b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs @@ -1,10 +1,18 @@ -using MediaBrowser.Common.Progress; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Progress; using MediaBrowser.Controller; using MediaBrowser.Controller.Sync; using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Sync; using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; using System.Threading; using System.Threading.Tasks; @@ -15,22 +23,25 @@ namespace MediaBrowser.Server.Implementations.Sync private readonly ISyncManager _syncManager; private readonly IServerApplicationHost _appHost; private readonly ILogger _logger; + private readonly IFileSystem _fileSystem; - public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost) + public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost, IFileSystem fileSystem) { _logger = logger; _syncManager = syncManager; _appHost = appHost; + _fileSystem = fileSystem; } public async Task Sync(IServerSyncProvider provider, + ISyncDataProvider dataProvider, SyncTarget target, IProgress progress, CancellationToken cancellationToken) { var serverId = _appHost.SystemId; - await SyncData(provider, serverId, target, cancellationToken).ConfigureAwait(false); + await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false); progress.Report(3); var innerProgress = new ActionableProgress(); @@ -40,44 +51,46 @@ namespace MediaBrowser.Server.Implementations.Sync totalProgress += 1; progress.Report(totalProgress); }); - await GetNewMedia(provider, target, serverId, innerProgress, cancellationToken); + await GetNewMedia(provider, dataProvider, target, serverId, innerProgress, cancellationToken); // Do the data sync twice so the server knows what was removed from the device - await SyncData(provider, serverId, target, cancellationToken).ConfigureAwait(false); + await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false); progress.Report(100); } private async Task SyncData(IServerSyncProvider provider, + ISyncDataProvider dataProvider, string serverId, SyncTarget target, CancellationToken cancellationToken) { - //var localIds = await provider.GetServerItemIds(serverId, target, cancellationToken).ConfigureAwait(false); + var localIds = await dataProvider.GetServerItemIds(target, serverId).ConfigureAwait(false); - //var result = await _syncManager.SyncData(new SyncDataRequest - //{ - // TargetId = target.Id, - // LocalItemIds = localIds + var result = await _syncManager.SyncData(new SyncDataRequest + { + TargetId = target.Id, + LocalItemIds = localIds - //}).ConfigureAwait(false); + }).ConfigureAwait(false); - //cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); - //foreach (var itemIdToRemove in result.ItemIdsToRemove) - //{ - // try - // { - // await RemoveItem(provider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false); - // } - // catch (Exception ex) - // { - // _logger.ErrorException("Error deleting item from sync target. Id: {0}", ex, itemIdToRemove); - // } - //} + foreach (var itemIdToRemove in result.ItemIdsToRemove) + { + try + { + await RemoveItem(provider, dataProvider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error deleting item from device. Id: {0}", ex, itemIdToRemove); + } + } } private async Task GetNewMedia(IServerSyncProvider provider, + ISyncDataProvider dataProvider, SyncTarget target, string serverId, IProgress progress, @@ -106,7 +119,7 @@ namespace MediaBrowser.Server.Implementations.Sync progress.Report(totalProgress); }); - await GetItem(provider, target, serverId, jobItem, innerProgress, cancellationToken).ConfigureAwait(false); + await GetItem(provider, dataProvider, target, serverId, jobItem, innerProgress, cancellationToken).ConfigureAwait(false); numComplete++; startingPercent = numComplete; @@ -117,6 +130,7 @@ namespace MediaBrowser.Server.Implementations.Sync } private async Task GetItem(IServerSyncProvider provider, + ISyncDataProvider dataProvider, SyncTarget target, string serverId, SyncedItem jobItem, @@ -129,6 +143,8 @@ namespace MediaBrowser.Server.Implementations.Sync var fileTransferProgress = new ActionableProgress(); fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92)); + var localItem = CreateLocalItem(provider, target, libraryItem, serverId, jobItem.OriginalFileName); + await _syncManager.ReportSyncJobItemTransferBeginning(internalSyncJobItem.Id); var transferSuccess = false; @@ -136,9 +152,10 @@ namespace MediaBrowser.Server.Implementations.Sync try { - string[] pathParts = GetPathParts(serverId, libraryItem); + await SendFile(provider, internalSyncJobItem.OutputPath, localItem, target, cancellationToken).ConfigureAwait(false); - await SendFile(provider, internalSyncJobItem.OutputPath, pathParts, target, cancellationToken).ConfigureAwait(false); + // Create db record + await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false); progress.Report(92); @@ -164,25 +181,189 @@ namespace MediaBrowser.Server.Implementations.Sync } } - private Task RemoveItem(IServerSyncProvider provider, + private async Task RemoveItem(IServerSyncProvider provider, + ISyncDataProvider dataProvider, string serverId, string itemId, SyncTarget target, CancellationToken cancellationToken) { - return Task.FromResult(true); - //return provider.DeleteItem(serverId, itemId, target, cancellationToken); + var localId = GetLocalId(serverId, itemId); + var localItem = await dataProvider.Get(target, localId); + + if (localItem == null) + { + return; + } + + var files = await GetFiles(provider, localItem, target); + + foreach (var file in files) + { + await provider.DeleteFile(file.Path, target, cancellationToken).ConfigureAwait(false); + } + + await dataProvider.Delete(target, localId).ConfigureAwait(false); + } + + private Task SendFile(IServerSyncProvider provider, string inputPath, LocalItem item, SyncTarget target, CancellationToken cancellationToken) + { + return provider.SendFile(inputPath, item.LocalPath, target, new Progress(), cancellationToken); + } + + private string GetLocalId(string serverId, string itemId) + { + var bytes = Encoding.UTF8.GetBytes(serverId + itemId); + bytes = CreateMD5(bytes); + return BitConverter.ToString(bytes, 0, bytes.Length).Replace("-", string.Empty); + } + + private byte[] CreateMD5(byte[] value) + { + using (var provider = MD5.Create()) + { + return provider.ComputeHash(value); + } } - private string[] GetPathParts(string serverId, BaseItemDto item) + public LocalItem CreateLocalItem(IServerSyncProvider provider, SyncTarget target, BaseItemDto libraryItem, string serverId, string originalFileName) { - return null; + var path = GetDirectoryPath(provider, libraryItem, serverId); + path.Add(GetLocalFileName(provider, libraryItem, originalFileName)); + + var localPath = provider.GetFullPath(path, target); + + foreach (var mediaSource in libraryItem.MediaSources) + { + mediaSource.Path = localPath; + mediaSource.Protocol = MediaProtocol.File; + } + + return new LocalItem + { + Item = libraryItem, + ItemId = libraryItem.Id, + ServerId = serverId, + LocalPath = localPath, + Id = GetLocalId(serverId, libraryItem.Id) + }; } - private async Task SendFile(IServerSyncProvider provider, string inputPath, string[] path, SyncTarget target, CancellationToken cancellationToken) + private List GetDirectoryPath(IServerSyncProvider provider, BaseItemDto item, string serverId) { - await provider.SendFile(inputPath, path, target, new Progress(), cancellationToken) - .ConfigureAwait(false); + var parts = new List + { + serverId + }; + + if (item.IsType("episode")) + { + parts.Add("TV"); + parts.Add(item.SeriesName); + + if (!string.IsNullOrWhiteSpace(item.SeasonName)) + { + parts.Add(item.SeasonName); + } + } + else if (item.IsVideo) + { + parts.Add("Videos"); + parts.Add(item.Name); + } + else if (item.IsAudio) + { + parts.Add("Music"); + + if (!string.IsNullOrWhiteSpace(item.AlbumArtist)) + { + parts.Add(item.AlbumArtist); + } + + if (!string.IsNullOrWhiteSpace(item.Album)) + { + parts.Add(item.Album); + } + } + else if (string.Equals(item.MediaType, MediaType.Photo, StringComparison.OrdinalIgnoreCase)) + { + parts.Add("Photos"); + + if (!string.IsNullOrWhiteSpace(item.Album)) + { + parts.Add(item.Album); + } + } + + return parts.Select(i => GetValidFilename(provider, i)).ToList(); + } + + private string GetLocalFileName(IServerSyncProvider provider, BaseItemDto item, string originalFileName) + { + var filename = originalFileName; + + if (string.IsNullOrEmpty(filename)) + { + filename = item.Name; + } + + return GetValidFilename(provider, filename); + } + + private string GetValidFilename(IServerSyncProvider provider, string filename) + { + // We can always add this method to the sync provider if it's really needed + return _fileSystem.GetValidFilename(filename); + } + + private async Task> GetFiles(IServerSyncProvider provider, LocalItem item, SyncTarget target) + { + var path = item.LocalPath; + path = provider.GetParentDirectoryPath(path, target); + + var list = await provider.GetFileSystemEntries(path, target).ConfigureAwait(false); + + var itemFiles = new List(); + + var name = Path.GetFileNameWithoutExtension(item.LocalPath); + + foreach (var file in list.Where(f => f.Name.Contains(name))) + { + var itemFile = new ItemFileInfo + { + Path = file.Path, + Name = file.Name + }; + + if (IsSubtitleFile(file.Name)) + { + itemFile.Type = ItemFileType.Subtitles; + } + else if (!IsImageFile(file.Name)) + { + itemFile.Type = ItemFileType.Media; + } + + itemFiles.Add(itemFile); + } + + return itemFiles; + } + + private static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".webp" }; + private bool IsImageFile(string path) + { + var ext = Path.GetExtension(path) ?? string.Empty; + + return SupportedImageExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase); + } + + private static readonly string[] SupportedSubtitleExtensions = { ".srt", ".vtt" }; + private bool IsSubtitleFile(string path) + { + var ext = Path.GetExtension(path) ?? string.Empty; + + return SupportedSubtitleExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase); } } } diff --git a/MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs b/MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs new file mode 100644 index 000000000..cbfa82f1d --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs @@ -0,0 +1,69 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Progress; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Sync; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Sync +{ + public class MultiProviderSync + { + private readonly ISyncManager _syncManager; + private readonly IServerApplicationHost _appHost; + private readonly ILogger _logger; + private readonly IFileSystem _fileSystem; + + public MultiProviderSync(ISyncManager syncManager, IServerApplicationHost appHost, ILogger logger, IFileSystem fileSystem) + { + _syncManager = syncManager; + _appHost = appHost; + _logger = logger; + _fileSystem = fileSystem; + } + + public async Task Sync(IEnumerable providers, IProgress progress, CancellationToken cancellationToken) + { + var targets = providers + .SelectMany(i => i.GetAllSyncTargets().Select(t => new Tuple(i, t))) + .ToList(); + + var numComplete = 0; + double startingPercent = 0; + double percentPerItem = 1; + if (targets.Count > 0) + { + percentPerItem /= targets.Count; + } + + foreach (var target in targets) + { + cancellationToken.ThrowIfCancellationRequested(); + + var currentPercent = startingPercent; + var innerProgress = new ActionableProgress(); + innerProgress.RegisterAction(pct => + { + var totalProgress = pct * percentPerItem; + totalProgress += currentPercent; + progress.Report(totalProgress); + }); + + await new MediaSync(_logger, _syncManager, _appHost, _fileSystem) + .Sync(target.Item1, target.Item1.GetDataProvider(), target.Item2, innerProgress, cancellationToken) + .ConfigureAwait(false); + + numComplete++; + startingPercent = numComplete; + startingPercent /= targets.Count; + startingPercent *= 100; + progress.Report(startingPercent); + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index a2fd92bf5..912967020 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -429,13 +429,6 @@ namespace MediaBrowser.Server.Implementations.Sync return (providerId + "-" + target.Id).GetMD5().ToString("N"); } - private ISyncProvider GetSyncProvider(SyncTarget target) - { - var providerId = target.Id.Split(new[] { '-' }, 2).First(); - - return _providers.First(i => string.Equals(providerId, GetSyncProviderId(i))); - } - private string GetSyncProviderId(ISyncProvider provider) { return (provider.GetType().Name).GetMD5().ToString("N"); @@ -547,7 +540,7 @@ namespace MediaBrowser.Server.Implementations.Sync { if (string.Equals(target.Id, targetId, StringComparison.OrdinalIgnoreCase)) { - return provider.GetDeviceProfile(target); + return GetDeviceProfile(provider, target); } } } @@ -555,6 +548,18 @@ namespace MediaBrowser.Server.Implementations.Sync return null; } + public DeviceProfile GetDeviceProfile(ISyncProvider provider, SyncTarget target) + { + var hasProfile = provider as IHasSyncProfile; + + if (hasProfile != null) + { + return hasProfile.GetDeviceProfile(target); + } + + return new CloudSyncProfile(true, false); + } + public async Task ReportSyncJobItemTransferred(string id) { var jobItem = _repo.GetJobItem(id); -- cgit v1.2.3 From 975f6899fe4bd580baf1c8869dd03fa7928ef743 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 28 Feb 2015 09:16:10 -0500 Subject: update ImageMagickSharp --- .../MediaBrowser.Server.Implementations.csproj | 2 +- MediaBrowser.Server.Implementations/packages.config | 2 +- MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj | 2 +- MediaBrowser.ServerApplication/packages.config | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj') diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 40aaa299f..fdd53b907 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -47,7 +47,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.3\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.4\lib\net45\ImageMagickSharp.dll False diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 0112d0f75..c97792fe0 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,6 +1,6 @@  - + diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 9750a4e45..984cca44b 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -62,7 +62,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.3\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.4\lib\net45\ImageMagickSharp.dll ..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index cfe7938de..5e4e31b86 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file -- cgit v1.2.3 From 0d8636d859cef5d0be4a723402926f05499210d7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 2 Mar 2015 00:16:29 -0500 Subject: update image magick sharp --- MediaBrowser.Controller/Library/IUserManager.cs | 1 + .../Notifications/NotificationType.cs | 3 +- .../Devices/CameraUploadsFolder.cs | 6 ++++ .../Drawing/ImageProcessor.cs | 40 +++------------------- .../EntryPoints/ActivityLogEntryPoint.cs | 12 +++++++ .../EntryPoints/Notifications/Notifications.cs | 18 +++++++++- .../Library/UserManager.cs | 13 +++++++ .../Localization/Server/server.json | 11 ++++++ .../MediaBrowser.Server.Implementations.csproj | 2 +- .../Notifications/CoreNotificationTypes.cs | 11 ++++++ .../Session/SessionManager.cs | 21 +++++++++--- .../packages.config | 2 +- .../MediaBrowser.ServerApplication.csproj | 2 +- MediaBrowser.ServerApplication/packages.config | 2 +- MediaBrowser.WebDashboard/Api/PackageCreator.cs | 1 + .../MediaBrowser.WebDashboard.csproj | 9 +++++ MediaBrowser.sln | 3 ++ 17 files changed, 111 insertions(+), 46 deletions(-) (limited to 'MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj') diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index 8119e5afb..a167cdbed 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -34,6 +34,7 @@ namespace MediaBrowser.Controller.Library event EventHandler> UserCreated; event EventHandler> UserConfigurationUpdated; event EventHandler> UserPasswordChanged; + event EventHandler> UserLockedOut; /// /// Gets a User by Id diff --git a/MediaBrowser.Model/Notifications/NotificationType.cs b/MediaBrowser.Model/Notifications/NotificationType.cs index 269e27a4f..f5e3624f0 100644 --- a/MediaBrowser.Model/Notifications/NotificationType.cs +++ b/MediaBrowser.Model/Notifications/NotificationType.cs @@ -19,6 +19,7 @@ namespace MediaBrowser.Model.Notifications NewLibraryContentMultiple, ServerRestartRequired, TaskFailed, - CameraImageUploaded + CameraImageUploaded, + UserLockedOut } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs index 2fe5d8f74..566f4c5f4 100644 --- a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs +++ b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities; +using System; using System.IO; using System.Linq; @@ -14,6 +15,11 @@ namespace MediaBrowser.Server.Implementations.Devices public override bool IsVisible(User user) { + if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase)) + { + return false; + } + return GetChildren(user, true).Any() && base.IsVisible(user); } diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs index c484a60db..180faa6bb 100644 --- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs +++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs @@ -350,9 +350,9 @@ namespace MediaBrowser.Server.Implementations.Drawing } /// - /// Increment this when indicator drawings change + /// Increment this when there's a change requiring caches to be invalidated /// - private const string IndicatorVersion = "2"; + private const string Version = "3"; /// /// Gets the cache file path based on a set of parameters @@ -371,29 +371,19 @@ namespace MediaBrowser.Server.Implementations.Drawing filename += "f=" + format; - var hasIndicator = false; - if (addPlayedIndicator) { filename += "pl=true"; - hasIndicator = true; } if (percentPlayed > 0) { filename += "p=" + percentPlayed; - hasIndicator = true; } if (unwatchedCount.HasValue) { filename += "p=" + unwatchedCount.Value; - hasIndicator = true; - } - - if (hasIndicator) - { - filename += "iv=" + IndicatorVersion; } if (!string.IsNullOrEmpty(backgroundColor)) @@ -401,6 +391,8 @@ namespace MediaBrowser.Server.Implementations.Drawing filename += "b=" + backgroundColor; } + filename += "v=" + Version; + return GetCachePath(ResizedImageCachePath, filename, "." + format.ToString().ToLower()); } @@ -671,30 +663,6 @@ namespace MediaBrowser.Server.Implementations.Drawing return enhancedImagePath; } - private ImageFormat GetFormat(string path) - { - var extension = Path.GetExtension(path); - - if (string.Equals(extension, ".png", StringComparison.OrdinalIgnoreCase)) - { - return ImageFormat.Png; - } - if (string.Equals(extension, ".gif", StringComparison.OrdinalIgnoreCase)) - { - return ImageFormat.Gif; - } - if (string.Equals(extension, ".webp", StringComparison.OrdinalIgnoreCase)) - { - return ImageFormat.Webp; - } - if (string.Equals(extension, ".bmp", StringComparison.OrdinalIgnoreCase)) - { - return ImageFormat.Bmp; - } - - return ImageFormat.Jpg; - } - /// /// Executes the image enhancers. /// diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs index 0b0661321..28883e9a2 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs @@ -86,6 +86,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _userManager.UserPasswordChanged += _userManager_UserPasswordChanged; _userManager.UserDeleted += _userManager_UserDeleted; _userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated; + _userManager.UserLockedOut += _userManager_UserLockedOut; //_config.ConfigurationUpdated += _config_ConfigurationUpdated; //_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; @@ -95,6 +96,16 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _appHost.ApplicationUpdated += _appHost_ApplicationUpdated; } + void _userManager_UserLockedOut(object sender, GenericEventArgs e) + { + CreateLogEntry(new ActivityLogEntry + { + Name = string.Format(_localization.GetLocalizedString("UserLockedOutWithName"), e.Argument.Name), + Type = "UserLockedOut", + UserId = e.Argument.Id.ToString("N") + }); + } + void _subManager_SubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e) { CreateLogEntry(new ActivityLogEntry @@ -482,6 +493,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _userManager.UserPasswordChanged -= _userManager_UserPasswordChanged; _userManager.UserDeleted -= _userManager_UserDeleted; _userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated; + _userManager.UserLockedOut -= _userManager_UserLockedOut; _config.ConfigurationUpdated -= _config_ConfigurationUpdated; _config.NamedConfigurationUpdated -= _config_NamedConfigurationUpdated; diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index 37bca4ddb..f6a35973b 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -78,6 +78,22 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications _appHost.HasUpdateAvailableChanged += _appHost_HasUpdateAvailableChanged; _appHost.ApplicationUpdated += _appHost_ApplicationUpdated; _deviceManager.CameraImageUploaded +=_deviceManager_CameraImageUploaded; + + _userManager.UserLockedOut += _userManager_UserLockedOut; + } + + async void _userManager_UserLockedOut(object sender, GenericEventArgs e) + { + var type = NotificationType.UserLockedOut.ToString(); + + var notification = new NotificationRequest + { + NotificationType = type + }; + + notification.Variables["UserName"] = e.Argument.Name; + + await SendNotification(notification).ConfigureAwait(false); } async void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs e) @@ -235,7 +251,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications return; } - var notification = new NotificationRequest { NotificationType = type @@ -471,6 +486,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications _appHost.ApplicationUpdated -= _appHost_ApplicationUpdated; _deviceManager.CameraImageUploaded -= _deviceManager_CameraImageUploaded; + _userManager.UserLockedOut -= _userManager_UserLockedOut; } private void DisposeLibraryUpdateTimer() diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 846bad214..00c674436 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -97,6 +97,7 @@ namespace MediaBrowser.Server.Implementations.Library /// public event EventHandler> UserUpdated; public event EventHandler> UserConfigurationUpdated; + public event EventHandler> UserLockedOut; /// /// Called when [user updated]. @@ -281,13 +282,25 @@ namespace MediaBrowser.Server.Implementations.Library 3 : 5; + var fireLockout = false; + if (newValue >= maxCount) { _logger.Debug("Disabling user {0} due to {1} unsuccessful login attempts.", user.Name, newValue.ToString(CultureInfo.InvariantCulture)); user.Policy.IsDisabled = true; + + fireLockout = true; } await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false); + + if (fireLockout) + { + if (UserLockedOut != null) + { + EventHelper.FireEventIfNotNull(UserLockedOut, this, new GenericEventArgs(user), _logger); + } + } } } diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 5f221a7be..2f593efcd 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -48,8 +48,10 @@ "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", "ButtonConvertMedia": "Convert media", "ButtonOrganize": "Organize", + "LabelPinCode": "Pin code:", "ButtonOk": "Ok", "ButtonCancel": "Cancel", + "ButtonExit": "Exit", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", @@ -57,6 +59,12 @@ "HeaderPaths": "Paths", "CategorySync": "Sync", "HeaderEasyPinCode": "Easy Pin Code", + "HeaderGrownupsOnly": "Grown-ups Only!", + "DividerOr": "-- or --", + "HeaderToAccessPleaseEnterEasyPinCode": "To access, please enter your easy pin code", + "KidsModeAdultInstruction": "Click the lock icon in the bottom right to configure or leave kids mode. Your pin code will be required.", + "ButtonConfigurePinCode": "Configure pin code", + "HeaderAdultsReadHere": "Adults Read Here!", "RegisterWithPayPal": "Register with PayPal", "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", @@ -670,6 +678,7 @@ "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", "NotificationOptionCameraImageUploaded": "Camera image uploaded", + "NotificationOptionUserLockedOut": "User locked out", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -1061,6 +1070,7 @@ "OptionBox": "Box", "OptionBoxRear": "Box rear", "OptionDisc": "Disc", + "OptionIcon": "Icon", "OptionLogo": "Logo", "OptionMenu": "Menu", "OptionScreenshot": "Screenshot", @@ -1105,6 +1115,7 @@ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", "LabelRunningTimeValue": "Running time: {0}", "LabelIpAddressValue": "Ip address: {0}", + "UserLockedOutWithName": "User {0} has been locked out", "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", "UserCreatedWithName": "User {0} has been created", "UserPasswordChangedWithName": "Password has been changed for user {0}", diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index fdd53b907..7833058f4 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -47,7 +47,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.4\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.5\lib\net45\ImageMagickSharp.dll False diff --git a/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs b/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs index d8acbe06c..a33fe2147 100644 --- a/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs +++ b/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs @@ -143,6 +143,13 @@ namespace MediaBrowser.Server.Implementations.Notifications Type = NotificationType.CameraImageUploaded.ToString(), DefaultTitle = "A new camera image has been uploaded from {DeviceName}.", Variables = new List{"DeviceName"} + }, + + new NotificationTypeInfo + { + Type = NotificationType.UserLockedOut.ToString(), + DefaultTitle = "{UserName} has been locked out.", + Variables = new List{"UserName"} } }; @@ -185,6 +192,10 @@ namespace MediaBrowser.Server.Implementations.Notifications { note.Category = _localization.GetLocalizedString("CategorySync"); } + else if (note.Type.IndexOf("UserLockedOut", StringComparison.OrdinalIgnoreCase) != -1) + { + note.Category = _localization.GetLocalizedString("CategoryUser"); + } else { note.Category = _localization.GetLocalizedString("CategorySystem"); diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index d02ef9d27..3ffbf5cb9 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -399,7 +399,7 @@ namespace MediaBrowser.Server.Implementations.Session Client = clientType, DeviceId = deviceId, ApplicationVersion = appVersion, - Id = Guid.NewGuid().ToString("N") + Id = key.GetMD5().ToString("N") }; sessionInfo.DeviceName = deviceName; @@ -798,6 +798,19 @@ namespace MediaBrowser.Server.Implementations.Session return session; } + private SessionInfo GetSessionToRemoteControl(string sessionId) + { + // Accept either device id or session id + var session = Sessions.FirstOrDefault(i => string.Equals(i.Id, sessionId)); + + if (session == null) + { + throw new ResourceNotFoundException(string.Format("Session {0} not found.", sessionId)); + } + + return session; + } + public Task SendMessageCommand(string controllingSessionId, string sessionId, MessageCommand command, CancellationToken cancellationToken) { var generalCommand = new GeneralCommand @@ -818,7 +831,7 @@ namespace MediaBrowser.Server.Implementations.Session public Task SendGeneralCommand(string controllingSessionId, string sessionId, GeneralCommand command, CancellationToken cancellationToken) { - var session = GetSession(sessionId); + var session = GetSessionToRemoteControl(sessionId); var controllingSession = GetSession(controllingSessionId); AssertCanControl(session, controllingSession); @@ -828,7 +841,7 @@ namespace MediaBrowser.Server.Implementations.Session public Task SendPlayCommand(string controllingSessionId, string sessionId, PlayRequest command, CancellationToken cancellationToken) { - var session = GetSession(sessionId); + var session = GetSessionToRemoteControl(sessionId); var user = session.UserId.HasValue ? _userManager.GetUserById(session.UserId.Value) : null; @@ -955,7 +968,7 @@ namespace MediaBrowser.Server.Implementations.Session public Task SendPlaystateCommand(string controllingSessionId, string sessionId, PlaystateRequest command, CancellationToken cancellationToken) { - var session = GetSession(sessionId); + var session = GetSessionToRemoteControl(sessionId); var controllingSession = GetSession(controllingSessionId); AssertCanControl(session, controllingSession); diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index c97792fe0..b83bee17d 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,6 +1,6 @@  - + diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index fcda32a33..019f1e977 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -62,7 +62,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.4\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.5\lib\net45\ImageMagickSharp.dll ..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 5e4e31b86..cf01ed666 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs index 1e188ceae..8328cf8ab 100644 --- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs +++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs @@ -421,6 +421,7 @@ namespace MediaBrowser.WebDashboard.Api "itembynamedetailpage.js", "itemdetailpage.js", "itemlistpage.js", + "kids.js", "librarypathmapping.js", "reports.js", "librarysettings.js", diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 812deabe1..fa6413b8b 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -87,6 +87,9 @@ + + PreserveNewest + PreserveNewest @@ -114,6 +117,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -129,6 +135,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 143a3da41..f73971374 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -520,4 +520,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection EndGlobal -- cgit v1.2.3 From f3159f3feff6a0ef11edb50cfc456f8c43d26d79 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 2 Mar 2015 13:48:21 -0500 Subject: update ProcessManager --- MediaBrowser.Api/Library/LibraryService.cs | 3 - .../MediaBrowser.Model.Portable.csproj | 6 ++ .../MediaBrowser.Model.net35.csproj | 6 ++ MediaBrowser.Model/Dlna/PlaybackErrorCode.cs | 9 +++ MediaBrowser.Model/Dlna/PlaybackException.cs | 9 +++ MediaBrowser.Model/Dlna/StreamBuilder.cs | 31 ++++++++- MediaBrowser.Model/Dto/MediaSourceInfo.cs | 2 + MediaBrowser.Model/MediaBrowser.Model.csproj | 2 + .../Library/Resolvers/TV/SeriesResolver.cs | 11 ++- .../MediaBrowser.Server.Implementations.csproj | 2 +- .../packages.config | 2 +- .../Diagnostics/ProcessManager.cs | 24 ------- .../MediaBrowser.Server.Mono.csproj | 1 - .../Diagnostics/ProcessManager.cs | 23 +++++++ .../MediaBrowser.Server.Startup.Common.csproj | 1 + .../MediaBrowser.ServerApplication.csproj | 3 +- .../Native/WindowsApp.cs | 3 +- .../Native/WindowsProcessManager.cs | 78 ---------------------- MediaBrowser.ServerApplication/packages.config | 2 +- 19 files changed, 97 insertions(+), 121 deletions(-) create mode 100644 MediaBrowser.Model/Dlna/PlaybackErrorCode.cs create mode 100644 MediaBrowser.Model/Dlna/PlaybackException.cs delete mode 100644 MediaBrowser.Server.Mono/Diagnostics/ProcessManager.cs create mode 100644 MediaBrowser.Server.Startup.Common/Diagnostics/ProcessManager.cs delete mode 100644 MediaBrowser.ServerApplication/Native/WindowsProcessManager.cs (limited to 'MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj') diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 85cc879f4..4d9afa260 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -1,5 +1,4 @@ using MediaBrowser.Controller.Activity; -using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -9,11 +8,9 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Session; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; using ServiceStack; using System; diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 37057f2d7..62677f818 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -362,6 +362,12 @@ Dlna\MediaFormatProfileResolver.cs + + Dlna\PlaybackErrorCode.cs + + + Dlna\PlaybackException.cs + Dlna\ProfileCondition.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index f38a8f597..4ed8cceae 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -327,6 +327,12 @@ Dlna\MediaFormatProfileResolver.cs + + Dlna\PlaybackErrorCode.cs + + + Dlna\PlaybackException.cs + Dlna\ProfileCondition.cs diff --git a/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs b/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs new file mode 100644 index 000000000..d8d65e91a --- /dev/null +++ b/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs @@ -0,0 +1,9 @@ + +namespace MediaBrowser.Model.Dlna +{ + public enum PlaybackErrorCode + { + NotAllowed = 0, + NoCompatibleStream = 1 + } +} diff --git a/MediaBrowser.Model/Dlna/PlaybackException.cs b/MediaBrowser.Model/Dlna/PlaybackException.cs new file mode 100644 index 000000000..761fa1c90 --- /dev/null +++ b/MediaBrowser.Model/Dlna/PlaybackException.cs @@ -0,0 +1,9 @@ +using System; + +namespace MediaBrowser.Model.Dlna +{ + public class PlaybackException : Exception + { + public PlaybackErrorCode ErrorCode { get; set;} + } +} diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index a40e4feb3..559a543f2 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -31,7 +31,13 @@ namespace MediaBrowser.Model.Dlna List streams = new List(); foreach (MediaSourceInfo i in mediaSources) - streams.Add(BuildAudioItem(i, options)); + { + StreamInfo streamInfo = BuildAudioItem(i, options); + if (streamInfo != null) + { + streams.Add(streamInfo); + } + } foreach (StreamInfo stream in streams) { @@ -63,7 +69,13 @@ namespace MediaBrowser.Model.Dlna List streams = new List(); foreach (MediaSourceInfo i in mediaSources) - streams.Add(BuildVideoItem(i, options)); + { + StreamInfo streamInfo = BuildVideoItem(i, options); + if (streamInfo != null) + { + streams.Add(streamInfo); + } + } foreach (StreamInfo stream in streams) { @@ -97,7 +109,10 @@ namespace MediaBrowser.Model.Dlna { return stream; } - return null; + + PlaybackException error = new PlaybackException(); + error.ErrorCode = PlaybackErrorCode.NoCompatibleStream; + throw error; } private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options) @@ -186,6 +201,11 @@ namespace MediaBrowser.Model.Dlna if (transcodingProfile != null) { + if (!item.SupportsTranscoding) + { + return null; + } + playlistItem.PlayMethod = PlayMethod.Transcode; playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength; @@ -290,6 +310,11 @@ namespace MediaBrowser.Model.Dlna if (transcodingProfile != null) { + if (!item.SupportsTranscoding) + { + return null; + } + if (subtitleStream != null) { SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile, options.Context); diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index 068443238..cdc97b7ea 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -22,6 +22,7 @@ namespace MediaBrowser.Model.Dto public long? RunTimeTicks { get; set; } public bool ReadAtNativeFramerate { get; set; } + public bool SupportsTranscoding { get; set; } public VideoType? VideoType { get; set; } @@ -45,6 +46,7 @@ namespace MediaBrowser.Model.Dto MediaStreams = new List(); RequiredHttpHeaders = new Dictionary(); PlayableStreamFileNames = new List(); + SupportsTranscoding = true; } public int? DefaultAudioStreamIndex { get; set; } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 9fd632cbd..27b5a53db 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -125,6 +125,8 @@ + + diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 7371ca5a9..3551b71b7 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -1,19 +1,18 @@ -using System.Collections.Generic; -using System.Linq; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; -using System; -using System.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Naming.Common; using MediaBrowser.Naming.IO; using MediaBrowser.Naming.TV; using MediaBrowser.Server.Implementations.Logging; -using EpisodeInfo = MediaBrowser.Controller.Providers.EpisodeInfo; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV { diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 7833058f4..a265ffdf1 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -47,7 +47,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.5\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.6\lib\net45\ImageMagickSharp.dll False diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index b83bee17d..8c530e015 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,6 +1,6 @@  - + diff --git a/MediaBrowser.Server.Mono/Diagnostics/ProcessManager.cs b/MediaBrowser.Server.Mono/Diagnostics/ProcessManager.cs deleted file mode 100644 index 05d1a4151..000000000 --- a/MediaBrowser.Server.Mono/Diagnostics/ProcessManager.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MediaBrowser.Controller.Diagnostics; -using System; -using System.Diagnostics; - -namespace MediaBrowser.Server.Mono.Diagnostics -{ - public class ProcessManager : IProcessManager - { - public void SuspendProcess(Process process) - { - throw new NotImplementedException(); - } - - public void ResumeProcess(Process process) - { - throw new NotImplementedException(); - } - - public bool SupportsSuspension - { - get { return false; } - } - } -} diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index 8b4783b5c..8f552ee36 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -75,7 +75,6 @@ Properties\SharedVersion.cs - diff --git a/MediaBrowser.Server.Startup.Common/Diagnostics/ProcessManager.cs b/MediaBrowser.Server.Startup.Common/Diagnostics/ProcessManager.cs new file mode 100644 index 000000000..d01756d0e --- /dev/null +++ b/MediaBrowser.Server.Startup.Common/Diagnostics/ProcessManager.cs @@ -0,0 +1,23 @@ +using MediaBrowser.Controller.Diagnostics; +using System.Diagnostics; + +namespace MediaBrowser.Server.Mono.Diagnostics +{ + public class ProcessManager : IProcessManager + { + public void SuspendProcess(Process process) + { + process.PriorityClass = ProcessPriorityClass.Idle; + } + + public void ResumeProcess(Process process) + { + process.PriorityClass = ProcessPriorityClass.Normal; + } + + public bool SupportsSuspension + { + get { return true; } + } + } +} diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index 38e07fde4..625b29d36 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -56,6 +56,7 @@ + diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 019f1e977..58830360e 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -62,7 +62,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.5\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.6\lib\net45\ImageMagickSharp.dll ..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll @@ -113,7 +113,6 @@ - diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 8d25b4f72..d518a82d4 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Diagnostics; using MediaBrowser.IsoMounter; using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Mono.Diagnostics; using MediaBrowser.Server.Startup.Common; using MediaBrowser.ServerApplication.Networking; using System.Collections.Generic; @@ -113,7 +114,7 @@ namespace MediaBrowser.ServerApplication.Native public IProcessManager GetProcessManager() { - return new WindowsProcessManager(); + return new ProcessManager(); } } } diff --git a/MediaBrowser.ServerApplication/Native/WindowsProcessManager.cs b/MediaBrowser.ServerApplication/Native/WindowsProcessManager.cs deleted file mode 100644 index f3497aef5..000000000 --- a/MediaBrowser.ServerApplication/Native/WindowsProcessManager.cs +++ /dev/null @@ -1,78 +0,0 @@ -using MediaBrowser.Controller.Diagnostics; -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace MediaBrowser.ServerApplication.Native -{ - public class WindowsProcessManager : IProcessManager - { - public void SuspendProcess(Process process) - { - process.Suspend(); - } - - public void ResumeProcess(Process process) - { - process.Resume(); - } - - public bool SupportsSuspension - { - get { return true; } - } - } - - public static class ProcessExtension - { - [DllImport("kernel32.dll")] - static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); - [DllImport("kernel32.dll")] - static extern uint SuspendThread(IntPtr hThread); - [DllImport("kernel32.dll")] - static extern int ResumeThread(IntPtr hThread); - - public static void Suspend(this Process process) - { - foreach (ProcessThread thread in process.Threads) - { - var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); - if (pOpenThread == IntPtr.Zero) - { - break; - } - SuspendThread(pOpenThread); - } - } - public static void Resume(this Process process) - { - foreach (ProcessThread thread in process.Threads) - { - var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); - if (pOpenThread == IntPtr.Zero) - { - break; - } - ResumeThread(pOpenThread); - } - } - public static void Print(this Process process) - { - Console.WriteLine("{0,8} {1}", process.Id, process.ProcessName); - } - } - - [Flags] - public enum ThreadAccess : int - { - TERMINATE = (0x0001), - SUSPEND_RESUME = (0x0002), - GET_CONTEXT = (0x0008), - SET_CONTEXT = (0x0010), - SET_INFORMATION = (0x0020), - QUERY_INFORMATION = (0x0040), - SET_THREAD_TOKEN = (0x0080), - IMPERSONATE = (0x0100), - DIRECT_IMPERSONATION = (0x0200) - } -} diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index cf01ed666..3dd0c908d 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file -- cgit v1.2.3 From 2fc0686c308e74654f4f7ef9ea6cf56fb61b5ff5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 3 Mar 2015 02:03:17 -0500 Subject: add date content added comparer --- MediaBrowser.Api/Playback/MediaInfoService.cs | 1 + MediaBrowser.Controller/Entities/Audio/Audio.cs | 2 +- MediaBrowser.Controller/Entities/Video.cs | 15 +++-- .../Library/IMediaSourceManager.cs | 18 ++++++ MediaBrowser.Model/Dlna/PlaybackErrorCode.cs | 3 +- .../Drawing/ImageHeader.cs | 3 +- .../Library/MediaSourceManager.cs | 55 +++++++++++++++++ .../MediaBrowser.Server.Implementations.csproj | 1 + .../Photos/BaseDynamicImageProvider.cs | 14 ++++- .../Photos/DynamicImageHelpers.cs | 15 ++++- .../Session/SessionManager.cs | 6 +- .../Sorting/DateLastMediaAddedComparer.cs | 70 ++++++++++++++++++++++ .../Sorting/DatePlayedComparer.cs | 1 - 13 files changed, 186 insertions(+), 18 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs (limited to 'MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj') diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 77178c8cc..330a8777c 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Api.Playback { [Route("/Items/{Id}/MediaInfo", "GET", Summary = "Gets live playback media info for an item")] + [Route("/Items/{Id}/PlaybackInfo", "GET", Summary = "Gets live playback media info for an item")] public class GetLiveMediaInfo : IReturn { [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 902447999..d868227d9 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -239,7 +239,7 @@ namespace MediaBrowser.Controller.Entities.Audio { Id = i.Id.ToString("N"), Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File, - MediaStreams = MediaSourceManager.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(), + MediaStreams = MediaSourceManager.GetMediaStreams(i.Id).ToList(), Name = i.Name, Path = enablePathSubstituion ? GetMappedPath(i.Path, locationType) : i.Path, RunTimeTicks = i.RunTimeTicks, diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index d4507bc33..a0c3a6cf9 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -420,12 +420,17 @@ namespace MediaBrowser.Controller.Entities return base.GetDeletePaths(); } - public virtual IEnumerable GetMediaStreams() + public IEnumerable GetMediaStreams() { - return MediaSourceManager.GetMediaStreams(new MediaStreamQuery + var mediaSource = GetMediaSources(false) + .FirstOrDefault(); + + if (mediaSource == null) { - ItemId = Id - }); + return new List(); + } + + return mediaSource.MediaStreams; } public virtual MediaStream GetDefaultVideoStream() @@ -474,7 +479,7 @@ namespace MediaBrowser.Controller.Entities private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video i, MediaSourceType type) { - var mediaStreams = MediaSourceManager.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }) + var mediaStreams = MediaSourceManager.GetMediaStreams(i.Id) .ToList(); var locationType = i.LocationType; diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index 4378bc85d..5d79f613d 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -1,11 +1,29 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; +using System; using System.Collections.Generic; namespace MediaBrowser.Controller.Library { public interface IMediaSourceManager { + /// + /// Gets the media streams. + /// + /// The item identifier. + /// IEnumerable<MediaStream>. + IEnumerable GetMediaStreams(Guid itemId); + /// + /// Gets the media streams. + /// + /// The media source identifier. + /// IEnumerable<MediaStream>. + IEnumerable GetMediaStreams(string mediaSourceId); + /// + /// Gets the media streams. + /// + /// The query. + /// IEnumerable<MediaStream>. IEnumerable GetMediaStreams(MediaStreamQuery query); } } diff --git a/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs b/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs index d8d65e91a..4ed412985 100644 --- a/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs +++ b/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs @@ -4,6 +4,7 @@ namespace MediaBrowser.Model.Dlna public enum PlaybackErrorCode { NotAllowed = 0, - NoCompatibleStream = 1 + NoCompatibleStream = 1, + RateLimitExceeded = 2 } } diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs b/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs index 81d4a786a..6287d0bb8 100644 --- a/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs +++ b/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs @@ -62,8 +62,9 @@ namespace MediaBrowser.Server.Implementations.Drawing logger.Info("Failed to read image header for {0}. Doing it the slow way.", path); } - using (var wand = new MagickWand(path)) + using (var wand = new MagickWand()) { + wand.PingImage(path); var img = wand.CurrentImage; return new ImageSize diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index a45757d13..6ce989b02 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; +using System; using System.Collections.Generic; using System.Linq; @@ -47,5 +48,59 @@ namespace MediaBrowser.Server.Implementations.Library { return true; } + + public IEnumerable GetMediaStreams(string mediaSourceId) + { + var list = GetMediaStreams(new MediaStreamQuery + { + ItemId = new Guid(mediaSourceId) + }); + + return GetMediaStreamsForItem(list); + } + + public IEnumerable GetMediaStreams(Guid itemId) + { + var list = GetMediaStreams(new MediaStreamQuery + { + ItemId = itemId + }); + + return GetMediaStreamsForItem(list); + } + + private IEnumerable GetMediaStreamsForItem(IEnumerable streams) + { + var list = streams.ToList(); + + var subtitleStreams = list + .Where(i => i.Type == MediaStreamType.Subtitle) + .ToList(); + + if (subtitleStreams.Count > 0) + { + var videoStream = list.FirstOrDefault(i => i.Type == MediaStreamType.Video); + + // This is abitrary but at some point it becomes too slow to extract subtitles on the fly + // We need to learn more about when this is the case vs. when it isn't + const int maxAllowedBitrateForExternalSubtitleStream = 10000000; + + var videoBitrate = videoStream == null ? maxAllowedBitrateForExternalSubtitleStream : videoStream.BitRate ?? maxAllowedBitrateForExternalSubtitleStream; + + foreach (var subStream in subtitleStreams) + { + var supportsExternalStream = StreamSupportsExternalStream(subStream); + + if (supportsExternalStream && videoBitrate >= maxAllowedBitrateForExternalSubtitleStream) + { + supportsExternalStream = false; + } + + subStream.SupportsExternalStream = supportsExternalStream; + } + } + + return list; + } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index a265ffdf1..54df9a86d 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -278,6 +278,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index e1f98c659..40b85dad1 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -108,7 +108,12 @@ namespace MediaBrowser.Server.Implementations.Photos protected Task GetThumbCollage(List items) { - return DynamicImageHelpers.GetThumbCollage(items.Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)).ToList(), + var files = items + .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)) + .Where(i => !string.IsNullOrWhiteSpace(i)) + .ToList(); + + return DynamicImageHelpers.GetThumbCollage(files, FileSystem, 1600, 900, @@ -117,7 +122,12 @@ namespace MediaBrowser.Server.Implementations.Photos protected Task GetSquareCollage(List items) { - return DynamicImageHelpers.GetSquareCollage(items.Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)).ToList(), + var files = items + .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)) + .Where(i => !string.IsNullOrWhiteSpace(i)) + .ToList(); + + return DynamicImageHelpers.GetSquareCollage(files, FileSystem, 800, ApplicationPaths); } diff --git a/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs b/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs index c2af9cdaf..e7cd2f4d2 100644 --- a/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs +++ b/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs @@ -4,6 +4,7 @@ using MediaBrowser.Common.IO; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Photos @@ -15,6 +16,11 @@ namespace MediaBrowser.Server.Implementations.Photos int width, int height, IApplicationPaths appPaths) { + if (files.Any(string.IsNullOrWhiteSpace)) + { + throw new ArgumentException("Empty file found in files list"); + } + if (files.Count < 3) { return await GetSingleImage(files, fileSystem).ConfigureAwait(false); @@ -27,7 +33,7 @@ namespace MediaBrowser.Server.Implementations.Photos int cellHeight = height; var index = 0; - using (var wand = new MagickWand(width, height, "transparent")) + using (var wand = new MagickWand(width, height, new PixelWand(ColorName.None, 1))) { for (var row = 0; row < rows; row++) { @@ -57,6 +63,11 @@ namespace MediaBrowser.Server.Implementations.Photos IFileSystem fileSystem, int size, IApplicationPaths appPaths) { + if (files.Any(string.IsNullOrWhiteSpace)) + { + throw new ArgumentException("Empty file found in files list"); + } + if (files.Count < 4) { return await GetSingleImage(files, fileSystem).ConfigureAwait(false); @@ -68,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Photos int singleSize = size / 2; var index = 0; - using (var wand = new MagickWand(size, size, "transparent")) + using (var wand = new MagickWand(size, size, new PixelWand(ColorName.None, 1))) { for (var row = 0; row < rows; row++) { diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 3ffbf5cb9..8eef8536a 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -1579,11 +1579,7 @@ namespace MediaBrowser.Server.Implementations.Session if (!string.IsNullOrWhiteSpace(mediaSourceId)) { - info.MediaStreams = _mediaSourceManager.GetMediaStreams(new MediaStreamQuery - { - ItemId = new Guid(mediaSourceId) - - }).ToList(); + info.MediaStreams = _mediaSourceManager.GetMediaStreams(mediaSourceId).ToList(); } return info; diff --git a/MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs new file mode 100644 index 000000000..68cd44ec9 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs @@ -0,0 +1,70 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Querying; +using System; +using System.Linq; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + public class DateLastMediaAddedComparer : IUserBaseItemComparer + { + /// + /// Gets or sets the user. + /// + /// The user. + public User User { get; set; } + + /// + /// Gets or sets the user manager. + /// + /// The user manager. + public IUserManager UserManager { get; set; } + + /// + /// Gets or sets the user data repository. + /// + /// The user data repository. + public IUserDataManager UserDataRepository { get; set; } + + /// + /// Compares the specified x. + /// + /// The x. + /// The y. + /// System.Int32. + public int Compare(BaseItem x, BaseItem y) + { + return GetDate(x).CompareTo(GetDate(y)); + } + + /// + /// Gets the date. + /// + /// The x. + /// DateTime. + private DateTime GetDate(BaseItem x) + { + var folder = x as Folder; + + if (folder != null) + { + return folder.GetRecursiveChildren(User, i => !i.IsFolder) + .Select(i => i.DateCreated) + .OrderByDescending(i => i) + .FirstOrDefault(); + } + + return x.DateCreated; + } + + /// + /// Gets the name. + /// + /// The name. + public string Name + { + get { return ItemSortBy.DateLastContentAdded; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs index 7605a7a50..c881591be 100644 --- a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -1,6 +1,5 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; using System; -- cgit v1.2.3