diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index 7779c2fc5d..cb60d1123e 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -198,8 +198,15 @@ namespace Emby.Drawing.ImageMagick { return; } - - // TODO + + Double opacity; + if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4; + + using (var pixel = new PixelWand("#000", opacity)) + using (var overlay = new MagickWand(wand.CurrentImage.Width, wand.CurrentImage.Height, pixel)) + { + wand.CurrentImage.CompositeImage(overlay, CompositeOperator.OverCompositeOp, 0, 0); + } } private void AutoOrientImage(MagickWand wand) diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 93eac058d6..9efa609efe 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Providers; +using System; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Users; @@ -6,6 +7,7 @@ using MoreLinq; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using System.Threading.Tasks; using MediaBrowser.Model.Configuration; namespace MediaBrowser.Controller.Entities.TV @@ -127,6 +129,30 @@ namespace MediaBrowser.Controller.Entities.TV get { return (IndexNumber ?? -1) == 0; } } + public override Task> GetItems(InternalItemsQuery query) + { + var user = query.User; + + Func filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); + + IEnumerable items; + + if (query.User == null) + { + items = query.Recursive + ? GetRecursiveChildren(filter) + : Children.Where(filter); + } + else + { + items = GetEpisodes(query.User).Where(filter); + } + + var result = PostFilterAndSort(items, query); + + return Task.FromResult(result); + } + /// /// Gets the episodes. /// diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 420b3c3135..aa07ab3781 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -157,6 +157,32 @@ namespace MediaBrowser.Controller.Entities.TV return GetSeasons(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); } + public override Task> GetItems(InternalItemsQuery query) + { + var user = query.User; + + Func filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); + + IEnumerable items; + + if (query.User == null) + { + items = query.Recursive + ? GetRecursiveChildren(filter) + : Children.Where(filter); + } + else + { + items = query.Recursive + ? GetRecursiveChildren(user, filter) + : GetSeasons(user).Where(filter); + } + + var result = PostFilterAndSort(items, query); + + return Task.FromResult(result); + } + public IEnumerable GetSeasons(User user, bool includeMissingSeasons, bool includeVirtualUnaired) { var seasons = base.GetChildren(user, true) diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index bc102bd40a..5527c16463 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -204,6 +204,8 @@ namespace MediaBrowser.Model.Configuration public int MigrationVersion { get; set; } + public bool DownloadImagesInAdvance { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 370187801e..73e09c1e6f 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -18,6 +18,7 @@ using System.Threading; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Providers.Manager @@ -520,6 +521,16 @@ namespace MediaBrowser.Providers.Manager private bool EnableImageStub(IHasImages item, ImageType type) { + if (item is LiveTvProgram) + { + return true; + } + + if (_config.Configuration.DownloadImagesInAdvance) + { + return false; + } + if (item.LocationType == LocationType.Remote || item.LocationType == LocationType.Virtual) { return true; diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index e18da565df..416cc51bd2 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -283,12 +283,7 @@ namespace MediaBrowser.Providers.Manager if (!string.IsNullOrWhiteSpace(person.ImageUrl) && !personEntity.HasImage(ImageType.Primary)) { - personEntity.SetImage(new ItemImageInfo - { - Path = person.ImageUrl, - Type = ImageType.Primary, - IsPlaceholder = true - }, 0); + await AddPersonImage(personEntity, person.ImageUrl, cancellationToken).ConfigureAwait(false); saveEntity = true; updateType = updateType | ItemUpdateType.ImageUpdate; @@ -302,6 +297,23 @@ namespace MediaBrowser.Providers.Manager } } + private async Task AddPersonImage(Person personEntity, string imageUrl, CancellationToken cancellationToken) + { + if (ServerConfigurationManager.Configuration.DownloadImagesInAdvance) + { + await ProviderManager.SaveImage(personEntity, imageUrl, null, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); + } + else + { + personEntity.SetImage(new ItemImageInfo + { + Path = imageUrl, + Type = ImageType.Primary, + IsPlaceholder = true + }, 0); + } + } + private readonly Task _cachedTask = Task.FromResult(true); protected virtual Task AfterMetadataRefresh(TItemType item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) { diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 25fda3ac10..5d0c90ccf3 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -696,8 +696,21 @@ namespace MediaBrowser.Server.Implementations.IO foreach (var watcher in _fileSystemWatchers.Values.ToList()) { + watcher.Created -= watcher_Changed; + watcher.Deleted -= watcher_Changed; + watcher.Renamed -= watcher_Changed; watcher.Changed -= watcher_Changed; - watcher.EnableRaisingEvents = false; + + try + { + watcher.EnableRaisingEvents = false; + } + catch (InvalidOperationException) + { + // Seeing this under mono on linux sometimes + // Collection was modified; enumeration operation may not execute. + } + watcher.Dispose(); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index ba39982622..1fbd3cb3e5 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -729,6 +729,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV var recordingFileName = _fileSystem.GetValidFilename(RecordingHelper.GetRecordingName(timer, info)).Trim() + ".ts"; recordPath = Path.Combine(recordPath, recordingFileName); + recordPath = EnsureFileUnique(recordPath); _fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath)); var recordingId = info.Id.GetMD5().ToString("N"); @@ -862,6 +863,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV } } + private string EnsureFileUnique(string path) + { + var originalPath = path; + var index = 1; + + while (_fileSystem.FileExists(path)) + { + var parent = Path.GetDirectoryName(originalPath); + var name = Path.GetFileNameWithoutExtension(originalPath); + name += "-" + index.ToString(CultureInfo.InvariantCulture); + + path = Path.ChangeExtension(Path.Combine(parent, name), Path.GetExtension(originalPath)); + index++; + } + + return path; + } + private async Task GetRecorder() { if (GetConfiguration().EnableRecordingEncoding) diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 3be39bb5e9..8e1f42608d 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -65,9 +65,9 @@ ..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll - + False - ..\packages\SocketHttpListener.1.0.0.25\lib\net45\SocketHttpListener.dll + ..\packages\SocketHttpListener.1.0.0.26\lib\net45\SocketHttpListener.dll diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 1074796c09..08953b0be5 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -983,6 +983,26 @@ namespace MediaBrowser.Server.Implementations.Session } } + if (user != null && command.ItemIds.Length == 1 && user.Configuration.EnableNextEpisodeAutoPlay) + { + var episode = _libraryManager.GetItemById(command.ItemIds[0]) as Episode; + if (episode != null) + { + var series = episode.Series; + if (series != null) + { + var episodes = series.GetEpisodes(user, false, false) + .SkipWhile(i => i.Id != episode.Id) + .ToList(); + + if (episodes.Count > 0) + { + command.ItemIds = episodes.Select(i => i.Id.ToString("N")).ToArray(); + } + } + } + } + var controllingSession = GetSession(controllingSessionId); AssertCanControl(session, controllingSession); if (controllingSession.UserId.HasValue) diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 03e6542819..e2e54e0569 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -338,6 +338,12 @@ namespace MediaBrowser.Server.Implementations.Sync return series.GetEpisodes(user, false, false); } + var season = item as Season; + if (season != null) + { + return season.GetEpisodes(user, false, false); + } + if (item.IsFolder) { var folder = (Folder)item; diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 6341e50baa..495bd058b3 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -7,5 +7,5 @@ - + \ No newline at end of file diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index d8ea39e62b..9b2dfca19d 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1057,306 +1057,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - PreserveNewest