From d155b78360a2d8a945aded31c361f69ad017e8b3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 18 Apr 2015 20:05:36 -0400 Subject: update hls timer --- MediaBrowser.Server.Implementations/Library/LibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/Library') diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 313985d9d..e99d01d54 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1723,7 +1723,7 @@ namespace MediaBrowser.Server.Implementations.Library await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); } - var refresh = isNew || (DateTime.UtcNow - item.DateLastSaved).TotalHours >= 12; + var refresh = isNew || (DateTime.UtcNow - item.DateLastSaved).TotalHours >= 24; if (refresh) { -- cgit v1.2.3 From 9e0c73ef1946cd49de43f972839af90c465dcfb1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 19 Apr 2015 15:17:17 -0400 Subject: live tv fixes --- Emby.Drawing/ImageProcessor.cs | 32 ++++++++-------------- MediaBrowser.Api/ApiEntryPoint.cs | 27 +++++++++++++++--- MediaBrowser.Controller/Entities/BaseItem.cs | 22 ++++----------- MediaBrowser.Controller/Entities/ItemImageInfo.cs | 6 ---- .../Manager/ItemImageProvider.cs | 1 - .../Dto/DtoService.cs | 5 +--- .../Library/UserViewManager.cs | 10 +++++-- .../LiveTv/LiveTvMediaSourceProvider.cs | 11 ++++++-- 8 files changed, 55 insertions(+), 59 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Library') diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 6d600c646..55c6f6455 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -158,22 +158,19 @@ namespace Emby.Drawing } var dateModified = options.Image.DateModified; - var length = options.Image.Length; if (options.CropWhiteSpace) { - var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified, length).ConfigureAwait(false); + var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified).ConfigureAwait(false); originalImagePath = tuple.Item1; dateModified = tuple.Item2; - length = tuple.Item3; } if (options.Enhancers.Count > 0) { var tuple = await GetEnhancedImage(new ItemImageInfo { - Length = length, DateModified = dateModified, Type = options.Image.Type, Path = originalImagePath @@ -182,7 +179,6 @@ namespace Emby.Drawing originalImagePath = tuple.Item1; dateModified = tuple.Item2; - length = tuple.Item3; } var originalImageSize = GetImageSize(originalImagePath, dateModified); @@ -199,7 +195,7 @@ namespace Emby.Drawing var quality = options.Quality ?? 90; var outputFormat = GetOutputFormat(options.OutputFormat); - var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, length, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor); + var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor); var semaphore = GetLock(cacheFilePath); @@ -240,11 +236,10 @@ namespace Emby.Drawing /// /// Crops whitespace from an image, caches the result, and returns the cached path /// - private async Task> GetWhitespaceCroppedImage(string originalImagePath, DateTime dateModified, long length) + private async Task> GetWhitespaceCroppedImage(string originalImagePath, DateTime dateModified) { var name = originalImagePath; name += "datemodified=" + dateModified.Ticks; - name += "length=" + length; var croppedImagePath = GetCachePath(CroppedWhitespaceImageCachePath, name, Path.GetExtension(originalImagePath)); @@ -270,7 +265,7 @@ namespace Emby.Drawing // We have to have a catch-all here because some of the .net image methods throw a plain old Exception _logger.ErrorException("Error cropping image {0}", ex, originalImagePath); - return new Tuple(originalImagePath, dateModified, length); + return new Tuple(originalImagePath, dateModified); } finally { @@ -280,11 +275,9 @@ namespace Emby.Drawing return GetResult(croppedImagePath); } - private Tuple GetResult(string path) + private Tuple GetResult(string path) { - var file = new FileInfo(path); - - return new Tuple(path, _fileSystem.GetLastWriteTimeUtc(file), file.Length); + return new Tuple(path, _fileSystem.GetLastWriteTimeUtc(path)); } /// @@ -295,7 +288,7 @@ namespace Emby.Drawing /// /// Gets the cache file path based on a set of parameters /// - private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, long length, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, string backgroundColor) + private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, string backgroundColor) { var filename = originalPath; @@ -306,7 +299,6 @@ namespace Emby.Drawing filename += "quality=" + quality; filename += "datemodified=" + dateModified.Ticks; - filename += "length=" + length; filename += "f=" + format; @@ -492,17 +484,16 @@ namespace Emby.Drawing var originalImagePath = image.Path; var dateModified = image.DateModified; var imageType = image.Type; - var length = image.Length; // Optimization if (imageEnhancers.Count == 0) { - return (originalImagePath + dateModified.Ticks + string.Empty + length).GetMD5().ToString("N"); + return (originalImagePath + dateModified.Ticks).GetMD5().ToString("N"); } // Cache name is created with supported enhancers combined with the last config change so we pick up new config changes var cacheKeys = imageEnhancers.Select(i => i.GetConfigurationCacheKey(item, imageType)).ToList(); - cacheKeys.Add(originalImagePath + dateModified.Ticks + string.Empty + length); + cacheKeys.Add(originalImagePath + dateModified.Ticks); return string.Join("|", cacheKeys.ToArray()).GetMD5().ToString("N"); } @@ -525,7 +516,7 @@ namespace Emby.Drawing return result.Item1; } - private async Task> GetEnhancedImage(ItemImageInfo image, + private async Task> GetEnhancedImage(ItemImageInfo image, IHasImages item, int imageIndex, List enhancers) @@ -533,7 +524,6 @@ namespace Emby.Drawing var originalImagePath = image.Path; var dateModified = image.DateModified; var imageType = image.Type; - var length = image.Length; try { @@ -553,7 +543,7 @@ namespace Emby.Drawing _logger.Error("Error enhancing image", ex); } - return new Tuple(originalImagePath, dateModified, length); + return new Tuple(originalImagePath, dateModified); } /// diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 26d3c6200..f59b1b7df 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -341,14 +341,17 @@ namespace MediaBrowser.Api timerDuration = 60000; } + job.PingTimeout = timerDuration; + job.LastPingDate = DateTime.UtcNow; + // Don't start the timer for playback checkins with progressive streaming if (job.Type != TranscodingJobType.Progressive || !isProgressCheckIn) { - job.StartKillTimer(timerDuration, OnTranscodeKillTimerStopped); + job.StartKillTimer(OnTranscodeKillTimerStopped); } else { - job.ChangeKillTimerIfStarted(timerDuration); + job.ChangeKillTimerIfStarted(); } } @@ -360,6 +363,15 @@ namespace MediaBrowser.Api { var job = (TranscodingJob)state; + if (!job.HasExited && job.Type != TranscodingJobType.Progressive) + { + if ((DateTime.UtcNow - job.LastPingDate).TotalMilliseconds < job.PingTimeout) + { + job.StartKillTimer(OnTranscodeKillTimerStopped); + return; + } + } + Logger.Debug("Transcoding kill timer stopped for JobId {0} PlaySessionId {1}. Killing transcoding", job.Id, job.PlaySessionId); KillTranscodingJob(job, path => true); @@ -626,6 +638,9 @@ namespace MediaBrowser.Api private readonly object _timerLock = new object(); + public DateTime LastPingDate { get; set; } + public int PingTimeout { get; set; } + public TranscodingJob(ILogger logger) { Logger = logger; @@ -654,12 +669,14 @@ namespace MediaBrowser.Api } } - public void StartKillTimer(int intervalMs, TimerCallback callback) + public void StartKillTimer(TimerCallback callback) { CheckHasExited(); lock (_timerLock) { + var intervalMs = PingTimeout; + if (KillTimer == null) { Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); @@ -673,7 +690,7 @@ namespace MediaBrowser.Api } } - public void ChangeKillTimerIfStarted(int intervalMs) + public void ChangeKillTimerIfStarted() { CheckHasExited(); @@ -681,6 +698,8 @@ namespace MediaBrowser.Api { if (KillTimer != null) { + var intervalMs = PingTimeout; + Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); KillTimer.Change(intervalMs, Timeout.Infinite); } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 73ede8179..22efd3fba 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1512,7 +1512,6 @@ namespace MediaBrowser.Controller.Entities image.Path = file.FullName; image.DateModified = imageInfo.DateModified; - image.Length = imageInfo.Length; } } @@ -1622,14 +1621,11 @@ namespace MediaBrowser.Controller.Entities return null; } - var fileInfo = new FileInfo(path); - return new ItemImageInfo { Path = path, - DateModified = FileSystem.GetLastWriteTimeUtc(fileInfo), - Type = imageType, - Length = fileInfo.Length + DateModified = FileSystem.GetLastWriteTimeUtc(path), + Type = imageType }; } @@ -1690,7 +1686,6 @@ namespace MediaBrowser.Controller.Entities else { existing.DateModified = FileSystem.GetLastWriteTimeUtc(newImage); - existing.Length = ((FileInfo)newImage).Length; } } @@ -1716,8 +1711,7 @@ namespace MediaBrowser.Controller.Entities { Path = file.FullName, Type = type, - DateModified = FileSystem.GetLastWriteTimeUtc(file), - Length = ((FileInfo)file).Length + DateModified = FileSystem.GetLastWriteTimeUtc(file) }; } @@ -1756,15 +1750,9 @@ namespace MediaBrowser.Controller.Entities FileSystem.SwapFiles(path1, path2); - var file1 = new FileInfo(info1.Path); - var file2 = new FileInfo(info2.Path); - // Refresh these values - info1.DateModified = FileSystem.GetLastWriteTimeUtc(file1); - info2.DateModified = FileSystem.GetLastWriteTimeUtc(file2); - - info1.Length = file1.Length; - info2.Length = file2.Length; + info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.Path); + info2.DateModified = FileSystem.GetLastWriteTimeUtc(info2.Path); return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); } diff --git a/MediaBrowser.Controller/Entities/ItemImageInfo.cs b/MediaBrowser.Controller/Entities/ItemImageInfo.cs index 1122de403..b36b818ff 100644 --- a/MediaBrowser.Controller/Entities/ItemImageInfo.cs +++ b/MediaBrowser.Controller/Entities/ItemImageInfo.cs @@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Entities /// The path. public string Path { get; set; } - /// - /// Gets or sets the length. - /// - /// The length. - public long Length { get; set; } - /// /// Gets or sets the type. /// diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index a3b569150..fc47b0259 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -384,7 +384,6 @@ namespace MediaBrowser.Providers.Manager else { currentImage.DateModified = _fileSystem.GetLastWriteTimeUtc(image.FileInfo); - currentImage.Length = ((FileInfo) image.FileInfo).Length; } } else diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 190b8fcf4..f44b7b5a8 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -828,14 +828,11 @@ namespace MediaBrowser.Server.Implementations.Dto if (!string.IsNullOrEmpty(chapterInfo.ImagePath)) { - var file = new FileInfo(chapterInfo.ImagePath); - dto.ImageTag = GetImageCacheTag(item, new ItemImageInfo { Path = chapterInfo.ImagePath, Type = ImageType.Chapter, - DateModified = _fileSystem.GetLastWriteTimeUtc(file), - Length = file.Length + DateModified = _fileSystem.GetLastWriteTimeUtc(chapterInfo.ImagePath) }); } diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index a21b19e04..823599fe5 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -202,9 +202,15 @@ namespace MediaBrowser.Server.Implementations.Library public async Task GetUserView(List parents, string viewType, string sortName, User user, CancellationToken cancellationToken) { + var name = _localizationManager.GetLocalizedString("ViewType" + viewType); + if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase))) { - var name = parents[0].Name; + if (!string.IsNullOrWhiteSpace(parents[0].Name)) + { + name = parents[0].Name; + } + var parentId = parents[0].Id; var enableRichView = !user.Configuration.PlainFolderViews.Contains(parentId.ToString("N"), StringComparer.OrdinalIgnoreCase); @@ -226,8 +232,6 @@ namespace MediaBrowser.Server.Implementations.Library } else { - var name = _localizationManager.GetLocalizedString("ViewType" + viewType); - return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 84b4053a1..38c93a696 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -122,7 +122,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken) { - var inputPaths = new[] { mediaSource.Path }; + var originalRuntime = mediaSource.RunTimeTicks; var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { @@ -131,8 +131,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, ExtractChapters = false - }, cancellationToken) - .ConfigureAwait(false); + }, cancellationToken).ConfigureAwait(false); mediaSource.Bitrate = info.Bitrate; mediaSource.Container = info.Container; @@ -146,6 +145,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv mediaSource.DefaultSubtitleStreamIndex = null; + // Null this out so that it will be treated like a live stream + if (!originalRuntime.HasValue) + { + mediaSource.RunTimeTicks = null; + } + var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio); if (audioStream == null || audioStream.Index == -1) -- cgit v1.2.3 From 623874ec8b6ea3c0fb2c9b0643298af1b94a4e6d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 20 Apr 2015 14:04:02 -0400 Subject: improve live stream pinging --- MediaBrowser.Api/ApiEntryPoint.cs | 44 +++++++++++--- MediaBrowser.Api/Playback/BaseStreamingService.cs | 1 + MediaBrowser.Controller/Library/ILibraryManager.cs | 2 + .../Configuration/ServerConfiguration.cs | 2 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 10 ++- .../MediaInfo/FFProbeVideoInfo.cs | 71 ++++++++++++++-------- .../Library/LibraryManager.cs | 14 ++++- .../Library/UserViewManager.cs | 37 ++++++----- 8 files changed, 124 insertions(+), 57 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Library') diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index f59b1b7df..e76dcb4a4 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Configuration; @@ -40,6 +41,7 @@ namespace MediaBrowser.Api private readonly ISessionManager _sessionManager; private readonly IFileSystem _fileSystem; + private readonly IMediaSourceManager _mediaSourceManager; public readonly SemaphoreSlim TranscodingStartLock = new SemaphoreSlim(1, 1); @@ -49,12 +51,15 @@ namespace MediaBrowser.Api /// The logger. /// The session manager. /// The configuration. - public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config, IFileSystem fileSystem) + /// The file system. + /// The media source manager. + public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager) { Logger = logger; _sessionManager = sessionManager; _config = config; _fileSystem = fileSystem; + _mediaSourceManager = mediaSourceManager; Instance = this; } @@ -133,6 +138,7 @@ namespace MediaBrowser.Api /// /// The path. /// The play session identifier. + /// The live stream identifier. /// The transcoding job identifier. /// The type. /// The process. @@ -142,6 +148,7 @@ namespace MediaBrowser.Api /// TranscodingJob. public TranscodingJob OnTranscodeBeginning(string path, string playSessionId, + string liveStreamId, string transcodingJobId, TranscodingJobType type, Process process, @@ -160,7 +167,8 @@ namespace MediaBrowser.Api DeviceId = deviceId, CancellationTokenSource = cancellationTokenSource, Id = transcodingJobId, - PlaySessionId = playSessionId + PlaySessionId = playSessionId, + LiveStreamId = liveStreamId }; _activeTranscodingJobs.Add(job); @@ -323,7 +331,7 @@ namespace MediaBrowser.Api } } - private void PingTimer(TranscodingJob job, bool isProgressCheckIn) + private async void PingTimer(TranscodingJob job, bool isProgressCheckIn) { if (job.HasExited) { @@ -353,6 +361,18 @@ namespace MediaBrowser.Api { job.ChangeKillTimerIfStarted(); } + + if (!string.IsNullOrWhiteSpace(job.LiveStreamId)) + { + try + { + await _mediaSourceManager.PingLiveStream(job.LiveStreamId, CancellationToken.None).ConfigureAwait(false); + } + catch (Exception ex) + { + Logger.ErrorException("Error closing live stream", ex); + } + } } /// @@ -365,9 +385,11 @@ namespace MediaBrowser.Api if (!job.HasExited && job.Type != TranscodingJobType.Progressive) { - if ((DateTime.UtcNow - job.LastPingDate).TotalMilliseconds < job.PingTimeout) + var timeSinceLastPing = (DateTime.UtcNow - job.LastPingDate).TotalMilliseconds; + + if (timeSinceLastPing < job.PingTimeout) { - job.StartKillTimer(OnTranscodeKillTimerStopped); + job.StartKillTimer(OnTranscodeKillTimerStopped, job.PingTimeout); return; } } @@ -589,6 +611,11 @@ namespace MediaBrowser.Api /// The play session identifier. public string PlaySessionId { get; set; } /// + /// Gets or sets the live stream identifier. + /// + /// The live stream identifier. + public string LiveStreamId { get; set; } + /// /// Gets or sets the path. /// /// The path. @@ -670,13 +697,16 @@ namespace MediaBrowser.Api } public void StartKillTimer(TimerCallback callback) + { + StartKillTimer(callback, PingTimeout); + } + + public void StartKillTimer(TimerCallback callback, int intervalMs) { CheckHasExited(); lock (_timerLock) { - var intervalMs = PingTimeout; - if (KillTimer == null) { Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 520c3b9dc..923af3816 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1010,6 +1010,7 @@ namespace MediaBrowser.Api.Playback var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath, state.Request.PlaySessionId, + state.MediaSource.LiveStreamId, transcodingId, TranscodingJobType, process, diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index d16589f07..c00912115 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -309,6 +309,7 @@ namespace MediaBrowser.Controller.Library /// The parent identifier. /// Type of the view. /// Name of the sort. + /// The unique identifier. /// The cancellation token. /// Task<UserView>. Task GetNamedView(User user, @@ -316,6 +317,7 @@ namespace MediaBrowser.Controller.Library string parentId, string viewType, string sortName, + string uniqueId, CancellationToken cancellationToken); /// diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 72f917438..ac9bd6b08 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -49,7 +49,7 @@ namespace MediaBrowser.Model.Configuration /// /// true if [enable user specific user views]; otherwise, false. public bool EnableUserSpecificUserViews { get; set; } - + /// /// Gets or sets the value pointing to the file system where the ssl certiifcate is located.. /// diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index e8ef171aa..30da8bb4c 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -456,10 +456,8 @@ namespace MediaBrowser.Model.Dlna playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue); } - if (!playlistItem.AudioBitrate.HasValue) - { - playlistItem.AudioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec); - } + int audioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec); + playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate); int? maxBitrateSetting = options.GetMaxBitrate(); // Honor max rate @@ -472,9 +470,9 @@ namespace MediaBrowser.Model.Dlna videoBitrate -= playlistItem.AudioBitrate.Value; } + // Make sure the video bitrate is lower than bitrate settings but at least 64k int currentValue = playlistItem.VideoBitrate ?? videoBitrate; - - playlistItem.VideoBitrate = Math.Min(videoBitrate, currentValue); + playlistItem.VideoBitrate = Math.Max(Math.Min(videoBitrate, currentValue), 64000); } } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index f4d8ddb1a..b53e31316 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -218,7 +218,7 @@ namespace MediaBrowser.Providers.MediaInfo await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false); - FetchEmbeddedInfo(video, mediaInfo); + FetchEmbeddedInfo(video, mediaInfo, options); video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270); @@ -358,11 +358,13 @@ namespace MediaBrowser.Providers.MediaInfo return _blurayExaminer.GetDiscInfo(path); } - private void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data) + private void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions options) { + var isFullRefresh = options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh; + if (!video.LockedFields.Contains(MetadataFields.OfficialRating)) { - if (!string.IsNullOrWhiteSpace(data.OfficialRating)) + if (!string.IsNullOrWhiteSpace(data.OfficialRating) || isFullRefresh) { video.OfficialRating = data.OfficialRating; } @@ -370,54 +372,75 @@ namespace MediaBrowser.Providers.MediaInfo if (!video.LockedFields.Contains(MetadataFields.Cast)) { - video.People.Clear(); - - foreach (var person in data.People) + if (video.People.Count == 0 || isFullRefresh) { - video.AddPerson(new PersonInfo + video.People.Clear(); + + foreach (var person in data.People) { - Name = person.Name, - Type = person.Type, - Role = person.Role - }); + video.AddPerson(new PersonInfo + { + Name = person.Name, + Type = person.Type, + Role = person.Role + }); + } } } if (!video.LockedFields.Contains(MetadataFields.Genres)) { - video.Genres.Clear(); - - foreach (var genre in data.Genres) + if (video.Genres.Count == 0 || isFullRefresh) { - video.AddGenre(genre); + video.Genres.Clear(); + + foreach (var genre in data.Genres) + { + video.AddGenre(genre); + } } } if (!video.LockedFields.Contains(MetadataFields.Studios)) { - video.Studios.Clear(); - - foreach (var studio in data.Studios) + if (video.Studios.Count == 0 || isFullRefresh) { - video.AddStudio(studio); + video.Studios.Clear(); + + foreach (var studio in data.Studios) + { + video.AddStudio(studio); + } } } if (data.ProductionYear.HasValue) { - video.ProductionYear = data.ProductionYear; + if (!video.ProductionYear.HasValue || isFullRefresh) + { + video.ProductionYear = data.ProductionYear; + } } if (data.PremiereDate.HasValue) { - video.PremiereDate = data.PremiereDate; + if (!video.PremiereDate.HasValue || isFullRefresh) + { + video.PremiereDate = data.PremiereDate; + } } if (data.IndexNumber.HasValue) { - video.IndexNumber = data.IndexNumber; + if (!video.IndexNumber.HasValue || isFullRefresh) + { + video.IndexNumber = data.IndexNumber; + } } if (data.ParentIndexNumber.HasValue) { - video.ParentIndexNumber = data.ParentIndexNumber; + if (!video.ParentIndexNumber.HasValue || isFullRefresh) + { + video.ParentIndexNumber = data.ParentIndexNumber; + } } // If we don't have a ProductionYear try and get it from PremiereDate @@ -428,7 +451,7 @@ namespace MediaBrowser.Providers.MediaInfo if (!video.LockedFields.Contains(MetadataFields.Overview)) { - if (!string.IsNullOrWhiteSpace(data.Overview)) + if (string.IsNullOrWhiteSpace(video.Overview) || isFullRefresh) { video.Overview = data.Overview; } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index e99d01d54..dcdf2aa7d 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1602,7 +1602,7 @@ namespace MediaBrowser.Server.Implementations.Library { if (ConfigurationManager.Configuration.EnableUserSpecificUserViews) { - return await GetNamedViewInternal(user, name, null, viewType, sortName, cancellationToken) + return await GetNamedViewInternal(user, name, null, viewType, sortName, null, cancellationToken) .ConfigureAwait(false); } @@ -1662,6 +1662,7 @@ namespace MediaBrowser.Server.Implementations.Library string parentId, string viewType, string sortName, + string uniqueId, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(parentId)) @@ -1669,7 +1670,7 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentNullException("parentId"); } - return GetNamedViewInternal(user, name, parentId, viewType, sortName, cancellationToken); + return GetNamedViewInternal(user, name, parentId, viewType, sortName, uniqueId, cancellationToken); } private async Task GetNamedViewInternal(User user, @@ -1677,6 +1678,7 @@ namespace MediaBrowser.Server.Implementations.Library string parentId, string viewType, string sortName, + string uniqueId, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(name)) @@ -1684,7 +1686,13 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentNullException("name"); } - var id = GetNewItemId("37_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty), typeof(UserView)); + var idValues = "37_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty); + if (!string.IsNullOrWhiteSpace(uniqueId)) + { + idValues += uniqueId; + } + + var id = GetNewItemId(idValues, typeof(UserView)); var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N")); diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index 823599fe5..5cff9046a 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.Server.Implementations.Library if (parents.Count > 0) { - list.Add(await GetUserView(parents, CollectionType.TvShows, string.Empty, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(parents, list, CollectionType.TvShows, string.Empty, user, cancellationToken).ConfigureAwait(false)); } parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase) || string.Equals(i.CollectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.CollectionType)) @@ -105,7 +105,7 @@ namespace MediaBrowser.Server.Implementations.Library if (parents.Count > 0) { - list.Add(await GetUserView(parents, CollectionType.Music, string.Empty, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(parents, list, CollectionType.Music, string.Empty, user, cancellationToken).ConfigureAwait(false)); } parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.CollectionType)) @@ -113,7 +113,7 @@ namespace MediaBrowser.Server.Implementations.Library if (parents.Count > 0) { - list.Add(await GetUserView(parents, CollectionType.Movies, string.Empty, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(parents, list, CollectionType.Movies, string.Empty, user, cancellationToken).ConfigureAwait(false)); } parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.Games, StringComparison.OrdinalIgnoreCase)) @@ -121,7 +121,7 @@ namespace MediaBrowser.Server.Implementations.Library if (parents.Count > 0) { - list.Add(await GetUserView(parents, CollectionType.Games, string.Empty, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(parents, list, CollectionType.Games, string.Empty, user, cancellationToken).ConfigureAwait(false)); } parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase)) @@ -129,7 +129,7 @@ namespace MediaBrowser.Server.Implementations.Library if (parents.Count > 0) { - list.Add(await GetUserView(parents, CollectionType.BoxSets, string.Empty, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(parents, list, CollectionType.BoxSets, string.Empty, user, cancellationToken).ConfigureAwait(false)); } parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase)) @@ -137,12 +137,12 @@ namespace MediaBrowser.Server.Implementations.Library if (parents.Count > 0) { - list.Add(await GetUserView(parents, CollectionType.Playlists, string.Empty, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(parents, list, CollectionType.Playlists, string.Empty, user, cancellationToken).ConfigureAwait(false)); } if (user.Configuration.DisplayFoldersView) { - list.Add(await GetUserView(new List(), CollectionType.Folders, "zz_" + CollectionType.Folders, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(new List(), list, CollectionType.Folders, "zz_" + CollectionType.Folders, user, cancellationToken).ConfigureAwait(false)); } if (query.IncludeExternalContent) @@ -169,7 +169,7 @@ namespace MediaBrowser.Server.Implementations.Library if (_liveTvManager.GetEnabledUsers().Select(i => i.Id.ToString("N")).Contains(query.UserId)) { //list.Add(await _liveTvManager.GetInternalLiveTvFolder(query.UserId, cancellationToken).ConfigureAwait(false)); - list.Add(await GetUserView(new List(), CollectionType.LiveTv, string.Empty, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(new List(), list, CollectionType.LiveTv, string.Empty, user, cancellationToken).ConfigureAwait(false)); } } @@ -190,7 +190,9 @@ namespace MediaBrowser.Server.Implementations.Library public Task GetUserSubView(string name, string parentId, string type, User user, string sortName, CancellationToken cancellationToken) { - return _libraryManager.GetNamedView(user, name, parentId, type, sortName, cancellationToken); + var uniqueId = parentId + "subview" + type; + + return _libraryManager.GetNamedView(user, name, parentId, type, sortName, uniqueId, cancellationToken); } public Task GetUserSubView(string parentId, string type, User user, string sortName, CancellationToken cancellationToken) @@ -200,7 +202,7 @@ namespace MediaBrowser.Server.Implementations.Library return GetUserSubView(name, parentId, type, user, sortName, cancellationToken); } - public async Task GetUserView(List parents, string viewType, string sortName, User user, CancellationToken cancellationToken) + public async Task GetUserView(List parents, List currentViews, string viewType, string sortName, User user, CancellationToken cancellationToken) { var name = _localizationManager.GetLocalizedString("ViewType" + viewType); @@ -215,7 +217,12 @@ namespace MediaBrowser.Server.Implementations.Library var enableRichView = !user.Configuration.PlainFolderViews.Contains(parentId.ToString("N"), StringComparer.OrdinalIgnoreCase); - if (_config.Configuration.EnableUserSpecificUserViews || !enableRichView) + if (!enableRichView || currentViews.OfType().Any(i => string.Equals(i.ViewType, viewType, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase))) + { + return await GetUserView(parentId, name, viewType, enableRichView, sortName, user, cancellationToken).ConfigureAwait(false); + } + + if (_config.Configuration.EnableUserSpecificUserViews) { viewType = enableRichView ? viewType : null; var view = await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false); @@ -230,16 +237,14 @@ namespace MediaBrowser.Server.Implementations.Library return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false); } - else - { - return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false); - } + + return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false); } public Task GetUserView(Guid parentId, string name, string viewType, bool enableRichView, string sortName, User user, CancellationToken cancellationToken) { viewType = enableRichView ? viewType : null; - return _libraryManager.GetNamedView(user, name, parentId.ToString("N"), viewType, sortName, cancellationToken); + return _libraryManager.GetNamedView(user, name, parentId.ToString("N"), viewType, sortName, null, cancellationToken); } public List>> GetLatestItems(LatestItemsQuery request) -- cgit v1.2.3