From d8d5dd487326dd3fccf4e9f30cd8f7e3783fcfda Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 12 Jan 2015 22:46:44 -0500 Subject: make channel access opt-in rather than opt out --- MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs index 4a807df7a..b18651a68 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs @@ -38,7 +38,8 @@ namespace MediaBrowser.Controller.MediaEncoding SubtitlePlaybackMode mode, string audioTrackLanguage) { - streams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages).ToList(); + streams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages) + .ToList(); var full = streams.Where(s => !s.IsForced); @@ -81,11 +82,9 @@ namespace MediaBrowser.Controller.MediaEncoding private static IEnumerable GetSortedStreams(IEnumerable streams, MediaStreamType type, List languagePreferences) { - var orderStreams = streams - .Where(i => i.Type == type); - // Give some preferance to external text subs for better performance - return orderStreams.OrderBy(i => + return streams.Where(i => i.Type == type) + .OrderBy(i => { var index = languagePreferences.FindIndex(l => string.Equals(i.Language, l, StringComparison.OrdinalIgnoreCase)); @@ -94,8 +93,7 @@ namespace MediaBrowser.Controller.MediaEncoding .ThenBy(i => i.IsDefault) .ThenBy(i => i.IsTextSubtitleStream) .ThenBy(i => i.IsExternal) - .ThenBy(i => i.Index) - .ToList(); + .ThenBy(i => i.Index); } } } -- cgit v1.2.3 From 0e02e0559d3873a35ca2ec911b3c0b714a7611ea Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 16 Jan 2015 23:29:53 -0500 Subject: sync updates --- MediaBrowser.Api/ApiEntryPoint.cs | 3 +- MediaBrowser.Api/Playback/BaseStreamingService.cs | 2 +- MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs | 8 +- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 3 +- MediaBrowser.Api/Sync/SyncService.cs | 30 ++- MediaBrowser.Controller/IServerApplicationHost.cs | 4 +- .../MediaEncoding/EncodingJobOptions.cs | 1 + MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 7 +- .../MediaBrowser.Model.Portable.csproj | 3 + .../MediaBrowser.Model.net35.csproj | 3 + MediaBrowser.Model/ApiClient/IApiClient.cs | 9 + MediaBrowser.Model/Dlna/StreamInfo.cs | 3 +- MediaBrowser.Model/Dlna/SubtitleStreamInfo.cs | 1 + MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + MediaBrowser.Model/Sync/ItemFIleInfo.cs | 7 +- MediaBrowser.Model/Sync/SyncDialogOptions.cs | 4 +- MediaBrowser.Model/Sync/SyncHelper.cs | 36 ++-- MediaBrowser.Model/Sync/SyncJobItem.cs | 22 ++- MediaBrowser.Model/Sync/SyncOptions.cs | 8 +- MediaBrowser.Model/Sync/SyncParameter.cs | 12 ++ MediaBrowser.Model/Sync/SyncedItem.cs | 11 ++ .../MediaBrowser.Server.Implementations.csproj | 1 + .../Session/SessionManager.cs | 18 +- .../Sync/SyncConfig.cs | 29 +++ .../Sync/SyncJobProcessor.cs | 207 ++++++++++++++++++--- .../Sync/SyncManager.cs | 44 +++-- .../Sync/SyncRepository.cs | 48 ++++- .../Sync/SyncScheduledTask.cs | 12 +- .../ApplicationHost.cs | 4 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Model.Signed.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 33 files changed, 437 insertions(+), 116 deletions(-) create mode 100644 MediaBrowser.Model/Sync/SyncParameter.cs create mode 100644 MediaBrowser.Server.Implementations/Sync/SyncConfig.cs (limited to 'MediaBrowser.Controller/MediaEncoding') diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index a9b43090a..ef415ec57 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -5,7 +5,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Session; using System; @@ -89,7 +88,7 @@ namespace MediaBrowser.Api /// private void DeleteEncodedMediaCache() { - var path = Path.Combine(_config.ApplicationPaths.TranscodingTempPath, EncodingContext.Streaming.ToString().ToLower()); + var path = _config.ApplicationPaths.TranscodingTempPath; foreach (var file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) .ToList()) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 2a0c5e01f..84dd0c1e8 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -119,7 +119,7 @@ namespace MediaBrowser.Api.Playback /// System.String. private string GetOutputFilePath(StreamState state) { - var folder = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, EncodingContext.Streaming.ToString().ToLower()); + var folder = ServerConfigurationManager.ApplicationPaths.TranscodingTempPath; var outputFileExtension = GetOutputFileExtension(state); diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index 14045b3a5..9f80fcd0a 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -1,10 +1,6 @@ using MediaBrowser.Controller; -using MediaBrowser.Model.Dlna; using ServiceStack; -using System; using System.IO; -using System.Linq; -using System.Threading.Tasks; namespace MediaBrowser.Api.Playback.Hls { @@ -66,7 +62,7 @@ namespace MediaBrowser.Api.Playback.Hls { var file = request.PlaylistId + Path.GetExtension(Request.PathInfo); - file = Path.Combine(_appPaths.TranscodingTempPath, EncodingContext.Streaming.ToString().ToLower(), file); + file = Path.Combine(_appPaths.TranscodingTempPath, file); return ResultFactory.GetStaticFileResult(Request, file, FileShare.ReadWrite); } @@ -85,7 +81,7 @@ namespace MediaBrowser.Api.Playback.Hls { var file = request.SegmentId + Path.GetExtension(Request.PathInfo); - file = Path.Combine(_appPaths.TranscodingTempPath, EncodingContext.Streaming.ToString().ToLower(), file); + file = Path.Combine(_appPaths.TranscodingTempPath, file); return ResultFactory.GetStaticFileResult(Request, file, FileShare.ReadWrite); } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index d786b51b3..de845c88d 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -5,7 +5,6 @@ using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Dlna; using MediaBrowser.Model.IO; using ServiceStack; using System; @@ -71,7 +70,7 @@ namespace MediaBrowser.Api.Playback.Hls { var file = request.SegmentId + Path.GetExtension(Request.PathInfo); - file = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, EncodingContext.Streaming.ToString().ToLower(), file); + file = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, file); return ResultFactory.GetStaticFileResult(Request, file); } diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs index a7467c12f..8d5ec824f 100644 --- a/MediaBrowser.Api/Sync/SyncService.cs +++ b/MediaBrowser.Api/Sync/SyncService.cs @@ -2,7 +2,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Sync; using MediaBrowser.Model.Users; @@ -85,6 +84,16 @@ namespace MediaBrowser.Api.Sync public string Id { get; set; } } + [Route("/Sync/JobItems/{Id}/AdditionalFiles", "GET", Summary = "Gets a sync job item file")] + public class GetSyncJobItemAdditionalFile + { + [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + + [ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string Name { get; set; } + } + [Route("/Sync/OfflineActions", "POST", Summary = "Reports an action that occurred while offline.")] public class ReportOfflineActions : List, IReturnVoid { @@ -243,5 +252,24 @@ namespace MediaBrowser.Api.Sync Task.WaitAll(task); } + + public object Get(GetSyncJobItemAdditionalFile request) + { + var jobItem = _syncManager.GetJobItem(request.Id); + + if (jobItem.Status != SyncJobItemStatus.Transferring) + { + throw new ArgumentException("The job item is not yet ready for transfer."); + } + + var file = jobItem.AdditionalFiles.FirstOrDefault(i => string.Equals(i.Name, request.Name, StringComparison.OrdinalIgnoreCase)); + + if (file == null) + { + throw new ArgumentException("Sync job additional file not found."); + } + + return ToStaticFileResult(file.Path); + } } } diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index d1a9b386c..76eb9fceb 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; -using MediaBrowser.Common; +using MediaBrowser.Common; using MediaBrowser.Model.System; using System; +using System.Collections.Generic; namespace MediaBrowser.Controller { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index a988c2f97..ad9ab90a0 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -5,6 +5,7 @@ namespace MediaBrowser.Controller.MediaEncoding public class EncodingJobOptions { public string OutputContainer { get; set; } + public string OutputDirectory { get; set; } public long? StartTimeTicks { get; set; } public int? Width { get; set; } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 4db4cd427..4dc522f05 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -280,13 +280,14 @@ namespace MediaBrowser.MediaEncoding.Encoder private string GetOutputFilePath(EncodingJob state) { - var folder = ConfigurationManager.ApplicationPaths.TranscodingTempPath; + var folder = string.IsNullOrWhiteSpace(state.Options.OutputDirectory) ? + ConfigurationManager.ApplicationPaths.TranscodingTempPath : + state.Options.OutputDirectory; var outputFileExtension = GetOutputFileExtension(state); - var context = state.Options.Context; var filename = state.Id + (outputFileExtension ?? string.Empty).ToLower(); - return Path.Combine(folder, context.ToString().ToLower(), filename); + return Path.Combine(folder, filename); } protected virtual string GetOutputFileExtension(EncodingJob state) diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index c49e3e303..de60a3e83 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -1094,6 +1094,9 @@ Sync\SyncOptions.cs + + Sync\SyncParameter.cs + Sync\SyncQuality.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index d8a29e8da..1cc1aac09 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -1053,6 +1053,9 @@ Sync\SyncOptions.cs + + Sync\SyncParameter.cs + Sync\SyncQuality.cs diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index bcba9230f..e8535278b 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -1413,6 +1413,15 @@ namespace MediaBrowser.Model.ApiClient /// Task<Stream>. Task GetSyncJobItemFile(string id, CancellationToken cancellationToken); + /// + /// Gets the synchronize job item additional file. + /// + /// The identifier. + /// The name. + /// The cancellation token. + /// Task<Stream>. + Task GetSyncJobItemAdditionalFile(string id, string name, CancellationToken cancellationToken); + /// /// Opens the web socket. /// diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 22eb0cf6c..acd2658a8 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -212,7 +212,8 @@ namespace MediaBrowser.Model.Dlna IsForced = stream.IsForced, Language = stream.Language, Name = stream.Language ?? "Unknown", - Format = SubtitleFormat + Format = SubtitleFormat, + Index = stream.Index }); } diff --git a/MediaBrowser.Model/Dlna/SubtitleStreamInfo.cs b/MediaBrowser.Model/Dlna/SubtitleStreamInfo.cs index 1600408d6..a7a8da3ba 100644 --- a/MediaBrowser.Model/Dlna/SubtitleStreamInfo.cs +++ b/MediaBrowser.Model/Dlna/SubtitleStreamInfo.cs @@ -7,5 +7,6 @@ namespace MediaBrowser.Model.Dlna public string Name { get; set; } public bool IsForced { get; set; } public string Format { get; set; } + public int Index { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 2a1b0b659..599e4a902 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -385,6 +385,7 @@ + diff --git a/MediaBrowser.Model/Sync/ItemFIleInfo.cs b/MediaBrowser.Model/Sync/ItemFIleInfo.cs index b110af6b5..e023572fd 100644 --- a/MediaBrowser.Model/Sync/ItemFIleInfo.cs +++ b/MediaBrowser.Model/Sync/ItemFIleInfo.cs @@ -23,6 +23,11 @@ namespace MediaBrowser.Model.Sync /// Gets or sets the type of the image. /// /// The type of the image. - public ImageType ImageType { get; set; } + public ImageType? ImageType { get; set; } + /// + /// Gets or sets the index. + /// + /// The index. + public int Index { get; set; } } } diff --git a/MediaBrowser.Model/Sync/SyncDialogOptions.cs b/MediaBrowser.Model/Sync/SyncDialogOptions.cs index 0154b16ec..304e10ccc 100644 --- a/MediaBrowser.Model/Sync/SyncDialogOptions.cs +++ b/MediaBrowser.Model/Sync/SyncDialogOptions.cs @@ -13,12 +13,12 @@ namespace MediaBrowser.Model.Sync /// Gets or sets the options. /// /// The options. - public List Options { get; set; } + public List Options { get; set; } public SyncDialogOptions() { Targets = new List(); - Options = new List(); + Options = new List(); } } } diff --git a/MediaBrowser.Model/Sync/SyncHelper.cs b/MediaBrowser.Model/Sync/SyncHelper.cs index c2a446fbe..34a5ba995 100644 --- a/MediaBrowser.Model/Sync/SyncHelper.cs +++ b/MediaBrowser.Model/Sync/SyncHelper.cs @@ -5,13 +5,13 @@ namespace MediaBrowser.Model.Sync { public static class SyncHelper { - public static List GetSyncOptions(List items) + public static List GetSyncOptions(List items) { - List options = new List(); + List options = new List(); if (items.Count > 1) { - options.Add(SyncOptions.Name); + options.Add(SyncJobOption.Name); } foreach (BaseItemDto item in items) @@ -20,23 +20,23 @@ namespace MediaBrowser.Model.Sync { if (item.IsVideo) { - options.Add(SyncOptions.Quality); + options.Add(SyncJobOption.Quality); if (items.Count > 1) { - options.Add(SyncOptions.UnwatchedOnly); + options.Add(SyncJobOption.UnwatchedOnly); } break; } if (item.IsFolder && !item.IsMusicGenre && !item.IsArtist && !item.IsType("musicalbum") && !item.IsGameGenre) { - options.Add(SyncOptions.Quality); - options.Add(SyncOptions.UnwatchedOnly); + options.Add(SyncJobOption.Quality); + options.Add(SyncJobOption.UnwatchedOnly); break; } if (item.IsGenre) { - options.Add(SyncOptions.SyncNewContent); - options.Add(SyncOptions.ItemLimit); + options.Add(SyncJobOption.SyncNewContent); + options.Add(SyncJobOption.ItemLimit); break; } } @@ -48,8 +48,8 @@ namespace MediaBrowser.Model.Sync { if (item.IsFolder || item.IsGameGenre || item.IsMusicGenre || item.IsGenre || item.IsArtist || item.IsStudio || item.IsPerson) { - options.Add(SyncOptions.SyncNewContent); - options.Add(SyncOptions.ItemLimit); + options.Add(SyncJobOption.SyncNewContent); + options.Add(SyncJobOption.ItemLimit); break; } } @@ -58,15 +58,15 @@ namespace MediaBrowser.Model.Sync return options; } - public static List GetSyncOptions(SyncCategory category) + public static List GetSyncOptions(SyncCategory category) { - List options = new List(); + List options = new List(); - options.Add(SyncOptions.Name); - options.Add(SyncOptions.Quality); - options.Add(SyncOptions.UnwatchedOnly); - options.Add(SyncOptions.SyncNewContent); - options.Add(SyncOptions.ItemLimit); + options.Add(SyncJobOption.Name); + options.Add(SyncJobOption.Quality); + options.Add(SyncJobOption.UnwatchedOnly); + options.Add(SyncJobOption.SyncNewContent); + options.Add(SyncJobOption.ItemLimit); return options; } diff --git a/MediaBrowser.Model/Sync/SyncJobItem.cs b/MediaBrowser.Model/Sync/SyncJobItem.cs index 3d06943aa..943014c0d 100644 --- a/MediaBrowser.Model/Sync/SyncJobItem.cs +++ b/MediaBrowser.Model/Sync/SyncJobItem.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using MediaBrowser.Model.Dto; namespace MediaBrowser.Model.Sync { @@ -27,12 +29,18 @@ namespace MediaBrowser.Model.Sync /// /// The name of the item. public string ItemName { get; set; } - + /// /// Gets or sets the media source identifier. /// /// The media source identifier. public string MediaSourceId { get; set; } + + /// + /// Gets or sets the media source. + /// + /// The media source. + public MediaSourceInfo MediaSource { get; set; } /// /// Gets or sets the target identifier. @@ -74,9 +82,15 @@ namespace MediaBrowser.Model.Sync /// The primary image tag. public string PrimaryImageTag { get; set; } /// - /// Gets or sets a value indicating whether [requires conversion]. + /// Gets or sets the temporary path. /// - /// true if [requires conversion]; otherwise, false. - public bool RequiresConversion { get; set; } + /// The temporary path. + public string TemporaryPath { get; set; } + public List AdditionalFiles { get; set; } + + public SyncJobItem() + { + AdditionalFiles = new List(); + } } } diff --git a/MediaBrowser.Model/Sync/SyncOptions.cs b/MediaBrowser.Model/Sync/SyncOptions.cs index d4a7461f3..294f7bcef 100644 --- a/MediaBrowser.Model/Sync/SyncOptions.cs +++ b/MediaBrowser.Model/Sync/SyncOptions.cs @@ -1,12 +1,8 @@  namespace MediaBrowser.Model.Sync { - public enum SyncOptions + public class SyncOptions { - Name = 0, - Quality = 1, - UnwatchedOnly = 2, - SyncNewContent = 3, - ItemLimit = 4 + public string TemporaryPath { get; set; } } } diff --git a/MediaBrowser.Model/Sync/SyncParameter.cs b/MediaBrowser.Model/Sync/SyncParameter.cs new file mode 100644 index 000000000..def4ab3e3 --- /dev/null +++ b/MediaBrowser.Model/Sync/SyncParameter.cs @@ -0,0 +1,12 @@ + +namespace MediaBrowser.Model.Sync +{ + public enum SyncJobOption + { + Name = 0, + Quality = 1, + UnwatchedOnly = 2, + SyncNewContent = 3, + ItemLimit = 4 + } +} diff --git a/MediaBrowser.Model/Sync/SyncedItem.cs b/MediaBrowser.Model/Sync/SyncedItem.cs index 784a12bc9..2063506b1 100644 --- a/MediaBrowser.Model/Sync/SyncedItem.cs +++ b/MediaBrowser.Model/Sync/SyncedItem.cs @@ -1,4 +1,5 @@ using MediaBrowser.Model.Dto; +using System.Collections.Generic; namespace MediaBrowser.Model.Sync { @@ -34,5 +35,15 @@ namespace MediaBrowser.Model.Sync /// /// The user identifier. public string UserId { get; set; } + /// + /// Gets or sets the additional files. + /// + /// The additional files. + public List AdditionalFiles { get; set; } + + public SyncedItem() + { + AdditionalFiles = new List(); + } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 433b76657..b4f277fbd 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -300,6 +300,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 8bf39fd6b..7112c2357 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -307,21 +307,21 @@ namespace MediaBrowser.Server.Implementations.Session /// The library item. private void UpdateNowPlayingItem(SessionInfo session, PlaybackProgressInfo info, BaseItem libraryItem) { - var runtimeTicks = libraryItem == null ? null : libraryItem.RunTimeTicks; - if (string.IsNullOrWhiteSpace(info.MediaSourceId)) { info.MediaSourceId = info.ItemId; } - if (!string.Equals(info.ItemId, info.MediaSourceId) && - !string.IsNullOrWhiteSpace(info.MediaSourceId)) + if (!string.IsNullOrWhiteSpace(info.ItemId) && info.Item == null && libraryItem != null) { - runtimeTicks = _libraryManager.GetItemById(new Guid(info.MediaSourceId)).RunTimeTicks; - } + var runtimeTicks = libraryItem.RunTimeTicks; + + if (!string.Equals(info.ItemId, info.MediaSourceId) && + !string.IsNullOrWhiteSpace(info.MediaSourceId)) + { + runtimeTicks = _libraryManager.GetItemById(new Guid(info.MediaSourceId)).RunTimeTicks; + } - if (!string.IsNullOrWhiteSpace(info.ItemId) && libraryItem != null) - { var current = session.NowPlayingItem; if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase)) @@ -711,7 +711,7 @@ namespace MediaBrowser.Server.Implementations.Session info.MediaSourceId = info.ItemId; } - if (!string.IsNullOrWhiteSpace(info.ItemId) && libraryItem != null) + if (!string.IsNullOrWhiteSpace(info.ItemId) && info.Item == null && libraryItem != null) { var current = session.NowPlayingItem; diff --git a/MediaBrowser.Server.Implementations/Sync/SyncConfig.cs b/MediaBrowser.Server.Implementations/Sync/SyncConfig.cs new file mode 100644 index 000000000..52c774330 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/SyncConfig.cs @@ -0,0 +1,29 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Sync; +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.Sync +{ + public class SyncConfigurationFactory : IConfigurationFactory + { + public IEnumerable GetConfigurations() + { + return new List + { + new ConfigurationStore + { + ConfigurationType = typeof(SyncOptions), + Key = "sync" + } + }; + } + } + + public static class SyncExtensions + { + public static SyncOptions GetSyncOptions(this IConfigurationManager config) + { + return config.GetConfiguration("sync"); + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 8053a3036..02c5aedd5 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -1,4 +1,7 @@ -using MediaBrowser.Common.Progress; +using System.Globalization; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Progress; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; @@ -16,6 +19,7 @@ using MediaBrowser.Model.Sync; using MoreLinq; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -32,8 +36,10 @@ namespace MediaBrowser.Server.Implementations.Sync private readonly ITVSeriesManager _tvSeriesManager; private readonly IMediaEncoder _mediaEncoder; private readonly ISubtitleEncoder _subtitleEncoder; + private readonly IConfigurationManager _config; + private readonly IFileSystem _fileSystem; - public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder) + public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem) { _libraryManager = libraryManager; _syncRepo = syncRepo; @@ -43,6 +49,8 @@ namespace MediaBrowser.Server.Implementations.Sync _tvSeriesManager = tvSeriesManager; _mediaEncoder = mediaEncoder; _subtitleEncoder = subtitleEncoder; + _config = config; + _fileSystem = fileSystem; } public async Task EnsureJobItems(SyncJob job) @@ -329,6 +337,13 @@ namespace MediaBrowser.Server.Implementations.Sync }); await SyncJobItems(result.Items, true, progress, cancellationToken).ConfigureAwait(false); + + CleanDeadSyncFiles(); + } + + private void CleanDeadSyncFiles() + { + // TODO } public async Task SyncJobItems(SyncJobItem[] items, bool enableConversion, IProgress progress, CancellationToken cancellationToken) @@ -416,24 +431,36 @@ namespace MediaBrowser.Server.Implementations.Sync var streamInfo = new StreamBuilder().BuildVideoItem(options); var mediaSource = streamInfo.MediaSource; + var externalSubs = streamInfo.GetExternalSubtitles("dummy", false); + var hasExternalSubs = externalSubs.Count > 0; - jobItem.MediaSourceId = streamInfo.MediaSourceId; + var requiresConversion = streamInfo.PlayMethod == PlayMethod.Transcode || hasExternalSubs; - if (streamInfo.PlayMethod == PlayMethod.Transcode) + if (requiresConversion && !enableConversion) { - if (!enableConversion) - { - return; - } + return; + } + jobItem.MediaSourceId = streamInfo.MediaSourceId; + jobItem.TemporaryPath = GetTemporaryPath(jobItem); + + if (requiresConversion) + { jobItem.Status = SyncJobItemStatus.Converting; - jobItem.RequiresConversion = true; + } + + if (streamInfo.PlayMethod == PlayMethod.Transcode) + { + // Save the job item now since conversion could take a while await _syncRepo.Update(jobItem).ConfigureAwait(false); try { - jobItem.OutputPath = await _mediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, profile), progress, - cancellationToken); + jobItem.OutputPath = await _mediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, profile) + { + OutputDirectory = jobItem.TemporaryPath + + }, progress, cancellationToken); } catch (OperationCanceledException) { @@ -445,18 +472,16 @@ namespace MediaBrowser.Server.Implementations.Sync _logger.ErrorException("Error during sync transcoding", ex); } - await ConvertSubtitles(jobItem, streamInfo, cancellationToken).ConfigureAwait(false); - if (jobItem.Status == SyncJobItemStatus.Failed || jobItem.Status == SyncJobItemStatus.Queued) { await _syncRepo.Update(jobItem).ConfigureAwait(false); return; } + + jobItem.MediaSource = await GetEncodedMediaSource(jobItem.OutputPath, user, true).ConfigureAwait(false); } else { - jobItem.RequiresConversion = false; - if (mediaSource.Protocol == MediaProtocol.File) { jobItem.OutputPath = mediaSource.Path; @@ -469,6 +494,16 @@ namespace MediaBrowser.Server.Implementations.Sync { throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); } + + jobItem.MediaSource = mediaSource; + } + + if (hasExternalSubs) + { + // Save the job item now since conversion could take a while + await _syncRepo.Update(jobItem).ConfigureAwait(false); + + await ConvertSubtitles(jobItem, externalSubs, streamInfo, cancellationToken).ConfigureAwait(false); } jobItem.Progress = 50; @@ -476,18 +511,72 @@ namespace MediaBrowser.Server.Implementations.Sync await _syncRepo.Update(jobItem).ConfigureAwait(false); } - private async Task ConvertSubtitles(SyncJobItem jobItem, StreamInfo streamInfo, CancellationToken cancellationToken) + private async Task ConvertSubtitles(SyncJobItem jobItem, + IEnumerable subtitles, + StreamInfo streamInfo, + CancellationToken cancellationToken) { - if (streamInfo.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External || !streamInfo.SubtitleStreamIndex.HasValue) + var files = new List(); + + var mediaStreams = jobItem.MediaSource.MediaStreams + .Where(i => i.Type != MediaStreamType.Subtitle || !i.IsExternal) + .ToList(); + + var startingIndex = mediaStreams.Count == 0 ? + 0 : + (mediaStreams.Select(i => i.Index).Max() + 1); + + foreach (var subtitle in subtitles) { - // Nothing to do - return; + var fileInfo = await ConvertSubtitles(jobItem.TemporaryPath, streamInfo, subtitle, cancellationToken).ConfigureAwait(false); + + // Reset this to a value that will be based on the output media + fileInfo.Index = startingIndex; + files.Add(fileInfo); + + mediaStreams.Add(new MediaStream + { + Index = startingIndex, + Codec = subtitle.Format, + IsForced = subtitle.IsForced, + IsExternal = true, + Language = subtitle.Language, + Path = fileInfo.Path + }); + + startingIndex++; } - //using (var stream = await _subtitleEncoder.GetSubtitles(streamInfo.ItemId, streamInfo.MediaSourceId, streamInfo.SubtitleStreamIndex.Value, streamInfo.SubtitleFormat, 0, null, cancellationToken).ConfigureAwait(false)) - //{ + jobItem.AdditionalFiles.AddRange(files); - //} + jobItem.MediaSource.MediaStreams = mediaStreams; + } + + private async Task ConvertSubtitles(string temporaryPath, StreamInfo streamInfo, SubtitleStreamInfo subtitleStreamInfo, CancellationToken cancellationToken) + { + var subtitleStreamIndex = subtitleStreamInfo.Index; + + var filename = Guid.NewGuid() + "." + subtitleStreamInfo.Format.ToLower(); + + var path = Path.Combine(temporaryPath, filename); + + Directory.CreateDirectory(Path.GetDirectoryName(path)); + + using (var stream = await _subtitleEncoder.GetSubtitles(streamInfo.ItemId, streamInfo.MediaSourceId, subtitleStreamIndex, subtitleStreamInfo.Format, 0, null, cancellationToken).ConfigureAwait(false)) + { + using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) + { + await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false); + } + } + + return new ItemFileInfo + { + Name = Path.GetFileName(path), + Path = path, + Type = ItemFileType.Subtitles, + Index = subtitleStreamIndex + }; } private async Task Sync(SyncJobItem jobItem, Audio item, User user, DeviceProfile profile, bool enableConversion, IProgress progress, CancellationToken cancellationToken) @@ -505,6 +594,7 @@ namespace MediaBrowser.Server.Implementations.Sync var mediaSource = streamInfo.MediaSource; jobItem.MediaSourceId = streamInfo.MediaSourceId; + jobItem.TemporaryPath = GetTemporaryPath(jobItem); if (streamInfo.PlayMethod == PlayMethod.Transcode) { @@ -514,12 +604,15 @@ namespace MediaBrowser.Server.Implementations.Sync } jobItem.Status = SyncJobItemStatus.Converting; - jobItem.RequiresConversion = true; await _syncRepo.Update(jobItem).ConfigureAwait(false); try { - jobItem.OutputPath = await _mediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, profile), progress, cancellationToken); + jobItem.OutputPath = await _mediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, profile) + { + OutputDirectory = jobItem.TemporaryPath + + }, progress, cancellationToken); } catch (OperationCanceledException) { @@ -536,11 +629,11 @@ namespace MediaBrowser.Server.Implementations.Sync await _syncRepo.Update(jobItem).ConfigureAwait(false); return; } + + jobItem.MediaSource = await GetEncodedMediaSource(jobItem.OutputPath, user, false).ConfigureAwait(false); } else { - jobItem.RequiresConversion = false; - if (mediaSource.Protocol == MediaProtocol.File) { jobItem.OutputPath = mediaSource.Path; @@ -553,6 +646,8 @@ namespace MediaBrowser.Server.Implementations.Sync { throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); } + + jobItem.MediaSource = mediaSource; } jobItem.Progress = 50; @@ -583,5 +678,65 @@ namespace MediaBrowser.Server.Implementations.Sync // TODO: Download return mediaSource.Path; } + + private string GetTemporaryPath(SyncJobItem jobItem) + { + var basePath = _config.GetSyncOptions().TemporaryPath; + + if (string.IsNullOrWhiteSpace(basePath)) + { + basePath = Path.Combine(_config.CommonApplicationPaths.ProgramDataPath, "sync"); + } + + return Path.Combine(basePath, jobItem.JobId, jobItem.Id); + } + + private async Task GetEncodedMediaSource(string path, User user, bool isVideo) + { + var item = _libraryManager.ResolvePath(new FileInfo(path)); + + await item.RefreshMetadata(CancellationToken.None).ConfigureAwait(false); + + var hasMediaSources = item as IHasMediaSources; + + var mediaSources = hasMediaSources.GetMediaSources(false).ToList(); + + var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference) + ? new string[] { } + : new[] { user.Configuration.AudioLanguagePreference }; + + var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference) + ? new List { } + : new List { user.Configuration.SubtitleLanguagePreference }; + + foreach (var source in mediaSources) + { + if (isVideo) + { + source.DefaultAudioStreamIndex = + MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.Configuration.PlayDefaultAudioTrack); + + var defaultAudioIndex = source.DefaultAudioStreamIndex; + var audioLangage = defaultAudioIndex == null + ? null + : source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault(); + + source.DefaultAudioStreamIndex = + MediaStreamSelector.GetDefaultSubtitleStreamIndex(source.MediaStreams, preferredSubs, user.Configuration.SubtitleMode, audioLangage); + } + else + { + var audio = source.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); + + if (audio != null) + { + source.DefaultAudioStreamIndex = audio.Index; + } + + } + } + + return mediaSources.FirstOrDefault(); + } } } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index bc6446d4e..b8d884cee 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Channels; @@ -13,6 +14,7 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Sync; using MediaBrowser.Controller.TV; using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; @@ -41,10 +43,11 @@ namespace MediaBrowser.Server.Implementations.Sync private readonly Func _mediaEncoder; private readonly IFileSystem _fileSystem; private readonly Func _subtitleEncoder; + private readonly IConfigurationManager _config; private ISyncProvider[] _providers = { }; - public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func dtoService, IApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func mediaEncoder, IFileSystem fileSystem, Func subtitleEncoder) + public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func dtoService, IApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func mediaEncoder, IFileSystem fileSystem, Func subtitleEncoder, IConfigurationManager config) { _libraryManager = libraryManager; _repo = repo; @@ -57,6 +60,7 @@ namespace MediaBrowser.Server.Implementations.Sync _mediaEncoder = mediaEncoder; _fileSystem = fileSystem; _subtitleEncoder = subtitleEncoder; + _config = config; } public void AddParts(IEnumerable providers) @@ -66,7 +70,7 @@ namespace MediaBrowser.Server.Implementations.Sync public async Task CreateJob(SyncJobRequest request) { - var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder(), _subtitleEncoder()); + var processor = GetSyncJobProcessor(); var user = _userManager.GetUserById(request.UserId); @@ -129,7 +133,7 @@ namespace MediaBrowser.Server.Implementations.Sync await _repo.Create(job).ConfigureAwait(false); await processor.EnsureJobItems(job).ConfigureAwait(false); - + // If it already has a converting status then is must have been aborted during conversion var jobItemsResult = _repo.GetJobItems(new SyncJobItemQuery { @@ -180,7 +184,7 @@ namespace MediaBrowser.Server.Implementations.Sync if (item == null) { - var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder(), _subtitleEncoder()); + var processor = GetSyncJobProcessor(); var user = _userManager.GetUserById(job.UserId); @@ -408,11 +412,14 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Status = SyncJobItemStatus.Synced; jobItem.Progress = 100; - if (jobItem.RequiresConversion) + if (!string.IsNullOrWhiteSpace(jobItem.TemporaryPath)) { try { - _fileSystem.DeleteFile(jobItem.OutputPath); + _fileSystem.DeleteDirectory(jobItem.TemporaryPath, true); + } + catch (DirectoryNotFoundException) + { } catch (Exception ex) { @@ -422,11 +429,16 @@ namespace MediaBrowser.Server.Implementations.Sync await _repo.Update(jobItem).ConfigureAwait(false); - var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder(), _subtitleEncoder()); + var processor = GetSyncJobProcessor(); await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); } + private SyncJobProcessor GetSyncJobProcessor() + { + return new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder(), _subtitleEncoder(), _config, _fileSystem); + } + public SyncJobItem GetJobItem(string id) { return _repo.GetJobItem(id); @@ -455,7 +467,15 @@ namespace MediaBrowser.Server.Implementations.Sync SyncJobId = jobItem.JobId, SyncJobItemId = jobItem.Id, ServerId = _appHost.SystemId, - UserId = job.UserId + UserId = job.UserId, + AdditionalFiles = jobItem.AdditionalFiles.Select(i => new ItemFileInfo + { + ImageType = i.ImageType, + Name = i.Name, + Type = i.Type, + Index = i.Index + + }).ToList() }; var dtoOptions = new DtoOptions(); @@ -472,14 +492,11 @@ namespace MediaBrowser.Server.Implementations.Sync syncedItem.Item = _dtoService().GetBaseItemDto(libraryItem, dtoOptions); - // TODO: this should be the media source of the transcoded output - syncedItem.Item.MediaSources = syncedItem.Item.MediaSources - .Where(i => string.Equals(i.Id, jobItem.MediaSourceId)) - .ToList(); - var mediaSource = syncedItem.Item.MediaSources .FirstOrDefault(i => string.Equals(i.Id, jobItem.MediaSourceId)); + syncedItem.Item.MediaSources = new List(); + // This will be null for items that are not audio/video if (mediaSource == null) { @@ -488,6 +505,7 @@ namespace MediaBrowser.Server.Implementations.Sync else { syncedItem.OriginalFileName = Path.GetFileName(mediaSource.Path); + syncedItem.Item.MediaSources.Add(mediaSource); } return syncedItem; diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 151860d84..ae9143710 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -1,7 +1,9 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Sync; using MediaBrowser.Server.Implementations.Persistence; using System; @@ -28,15 +30,18 @@ namespace MediaBrowser.Server.Implementations.Sync private IDbCommand _saveJobCommand; private IDbCommand _saveJobItemCommand; - public SyncRepository(ILogger logger, IServerApplicationPaths appPaths) + private readonly IJsonSerializer _json; + + public SyncRepository(ILogger logger, IServerApplicationPaths appPaths, IJsonSerializer json) { _logger = logger; _appPaths = appPaths; + _json = json; } public async Task Initialize() { - var dbFile = Path.Combine(_appPaths.DataPath, "sync11.db"); + var dbFile = Path.Combine(_appPaths.DataPath, "sync12.db"); _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); @@ -45,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.Sync "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT NOT NULL, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)", "create index if not exists idx_SyncJobs on SyncJobs(Id)", - "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, RequiresConversion BIT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT)", + "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, TemporaryPath TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT, AdditionalFiles TEXT, MediaSource TEXT)", "create index if not exists idx_SyncJobItems on SyncJobs(Id)", //pragmas @@ -90,23 +95,25 @@ namespace MediaBrowser.Server.Implementations.Sync _saveJobCommand.Parameters.Add(_saveJobCommand, "@ItemCount"); _saveJobItemCommand = _connection.CreateCommand(); - _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, RequiresConversion, OutputPath, Status, TargetId, DateCreated, Progress) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @RequiresConversion, @OutputPath, @Status, @TargetId, @DateCreated, @Progress)"; + _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource)"; _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Id"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@ItemId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@ItemName"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@MediaSourceId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@JobId"); - _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@RequiresConversion"); + _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@TemporaryPath"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@OutputPath"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Status"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@TargetId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@DateCreated"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Progress"); + _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@AdditionalFiles"); + _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@MediaSource"); } private const string BaseJobSelectText = "select Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs"; - private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, RequiresConversion, OutputPath, Status, TargetId, DateCreated, Progress from SyncJobItems"; + private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource from SyncJobItems"; public SyncJob GetJob(string id) { @@ -557,12 +564,14 @@ namespace MediaBrowser.Server.Implementations.Sync _saveJobItemCommand.GetParameter(index++).Value = jobItem.ItemName; _saveJobItemCommand.GetParameter(index++).Value = jobItem.MediaSourceId; _saveJobItemCommand.GetParameter(index++).Value = jobItem.JobId; - _saveJobItemCommand.GetParameter(index++).Value = jobItem.RequiresConversion; + _saveJobItemCommand.GetParameter(index++).Value = jobItem.TemporaryPath; _saveJobItemCommand.GetParameter(index++).Value = jobItem.OutputPath; _saveJobItemCommand.GetParameter(index++).Value = jobItem.Status.ToString(); _saveJobItemCommand.GetParameter(index++).Value = jobItem.TargetId; _saveJobItemCommand.GetParameter(index++).Value = jobItem.DateCreated; _saveJobItemCommand.GetParameter(index++).Value = jobItem.Progress; + _saveJobItemCommand.GetParameter(index++).Value = _json.SerializeToString(jobItem.AdditionalFiles); + _saveJobItemCommand.GetParameter(index++).Value = jobItem.MediaSource == null ? null : _json.SerializeToString(jobItem.MediaSource); _saveJobItemCommand.Transaction = transaction; @@ -620,8 +629,11 @@ namespace MediaBrowser.Server.Implementations.Sync } info.JobId = reader.GetString(4); - info.RequiresConversion = reader.GetBoolean(5); + if (!reader.IsDBNull(5)) + { + info.TemporaryPath = reader.GetString(5); + } if (!reader.IsDBNull(6)) { info.OutputPath = reader.GetString(6); @@ -641,6 +653,26 @@ namespace MediaBrowser.Server.Implementations.Sync info.Progress = reader.GetDouble(10); } + if (!reader.IsDBNull(11)) + { + var json = reader.GetString(11); + + if (!string.IsNullOrWhiteSpace(json)) + { + info.AdditionalFiles = _json.DeserializeFromString>(json); + } + } + + if (!reader.IsDBNull(12)) + { + var json = reader.GetString(12); + + if (!string.IsNullOrWhiteSpace(json)) + { + info.MediaSource = _json.DeserializeFromString(json); + } + } + return info; } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs b/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs index 88b761a7d..4edebb60f 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs @@ -1,4 +1,6 @@ -using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Sync; @@ -21,8 +23,10 @@ namespace MediaBrowser.Server.Implementations.Sync private readonly ITVSeriesManager _tvSeriesManager; private readonly IMediaEncoder _mediaEncoder; private readonly ISubtitleEncoder _subtitleEncoder; + private readonly IConfigurationManager _config; + private readonly IFileSystem _fileSystem; - public SyncScheduledTask(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder) + public SyncScheduledTask(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem) { _libraryManager = libraryManager; _syncRepo = syncRepo; @@ -32,6 +36,8 @@ namespace MediaBrowser.Server.Implementations.Sync _tvSeriesManager = tvSeriesManager; _mediaEncoder = mediaEncoder; _subtitleEncoder = subtitleEncoder; + _config = config; + _fileSystem = fileSystem; } public string Name @@ -54,7 +60,7 @@ namespace MediaBrowser.Server.Implementations.Sync public Task Execute(CancellationToken cancellationToken, IProgress progress) { - return new SyncJobProcessor(_libraryManager, _syncRepo, _syncManager, _logger, _userManager, _tvSeriesManager, _mediaEncoder, _subtitleEncoder).Sync(progress, + return new SyncJobProcessor(_libraryManager, _syncRepo, _syncManager, _logger, _userManager, _tvSeriesManager, _mediaEncoder, _subtitleEncoder, _config, _fileSystem).Sync(progress, cancellationToken); } diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 65d3b009f..f7ff5eef1 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -483,7 +483,7 @@ namespace MediaBrowser.Server.Startup.Common TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager); RegisterSingleInstance(TVSeriesManager); - SyncManager = new SyncManager(LibraryManager, SyncRepository, ImageProcessor, LogManager.GetLogger("SyncManager"), UserManager, () => DtoService, this, TVSeriesManager, () => MediaEncoder, FileSystemManager, () => SubtitleEncoder); + SyncManager = new SyncManager(LibraryManager, SyncRepository, ImageProcessor, LogManager.GetLogger("SyncManager"), UserManager, () => DtoService, this, TVSeriesManager, () => MediaEncoder, FileSystemManager, () => SubtitleEncoder, ServerConfigurationManager); RegisterSingleInstance(SyncManager); DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, SyncManager, this); @@ -663,7 +663,7 @@ namespace MediaBrowser.Server.Startup.Common private async Task GetSyncRepository() { - var repo = new SyncRepository(LogManager.GetLogger("SyncRepository"), ServerConfigurationManager.ApplicationPaths); + var repo = new SyncRepository(LogManager.GetLogger("SyncRepository"), ServerConfigurationManager.ApplicationPaths, JsonSerializer); await repo.Initialize().ConfigureAwait(false); diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index b2e8ce207..2f875f536 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.541 + 3.0.543 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 06fbc750f..7224a73cb 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.541 + 3.0.543 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index c11f886c1..f5a3a3de0 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.541 + 3.0.543 MediaBrowser.Model - Signed Edition Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index d183c9931..e3cbe9d04 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.541 + 3.0.543 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - + -- cgit v1.2.3 From cefd565e67ce3b8225eb2fa8a7338dc4d85b458d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 18 Jan 2015 14:53:34 -0500 Subject: display server name in dashboard --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 2 +- .../MediaEncoding/ISubtitleEncoder.cs | 3 +- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 2 +- .../Subtitles/SubtitleEncoder.cs | 65 +++++++++++++--------- .../Configuration/ServerConfiguration.cs | 3 - MediaBrowser.Providers/Movies/MovieDbSearch.cs | 9 +-- .../HttpServer/HttpListenerHost.cs | 11 ---- .../HttpServer/ServerFactory.cs | 6 +- .../Localization/JavaScript/javascript.json | 3 + .../Localization/Server/server.json | 4 +- .../ApplicationHost.cs | 14 +---- 11 files changed, 52 insertions(+), 70 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 56dc38e91..9253bc369 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -629,7 +629,7 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrEmpty(state.SubtitleStream.Language)) { - var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.SubtitleStream.Language); + var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath); if (!string.IsNullOrEmpty(charenc)) { diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs index 9e32fc32b..37c2bf4d2 100644 --- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs @@ -47,9 +47,8 @@ namespace MediaBrowser.Controller.MediaEncoding /// Gets the subtitle language encoding parameter. /// /// The path. - /// The language. /// System.String. - string GetSubtitleFileCharacterSet(string path, string language); + string GetSubtitleFileCharacterSet(string path); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index b357b0417..344eb9fbd 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -1015,7 +1015,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrEmpty(state.SubtitleStream.Language)) { - var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.SubtitleStream.Language); + var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath); if (!string.IsNullOrEmpty(charenc)) { diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 10d8112ff..4723525e3 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -149,22 +149,22 @@ namespace MediaBrowser.MediaEncoding.Subtitles var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, subtitleStream, cancellationToken).ConfigureAwait(false); - var stream = await GetSubtitleStream(fileInfo.Item1, subtitleStream.Language, fileInfo.Item3).ConfigureAwait(false); + var stream = await GetSubtitleStream(fileInfo.Item1, fileInfo.Item3).ConfigureAwait(false); return new Tuple(stream, fileInfo.Item2); } - private async Task GetSubtitleStream(string path, string language, bool requiresCharset) + private async Task GetSubtitleStream(string path, bool requiresCharset) { - if (requiresCharset && !string.IsNullOrEmpty(language)) + if (requiresCharset) { - var charset = GetSubtitleFileCharacterSet(path, language); + var charset = GetSubtitleFileCharacterSet(path); if (!string.IsNullOrEmpty(charset)) { using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) { - using (var reader = new StreamReader(fs, Encoding.GetEncoding(charset))) + using (var reader = new StreamReader(fs, GetEncoding(charset))) { var text = await reader.ReadToEndAsync().ConfigureAwait(false); @@ -179,6 +179,23 @@ namespace MediaBrowser.MediaEncoding.Subtitles return File.OpenRead(path); } + private Encoding GetEncoding(string charset) + { + if (string.IsNullOrWhiteSpace(charset)) + { + throw new ArgumentNullException("charset"); + } + + try + { + return Encoding.GetEncoding(charset); + } + catch (ArgumentException) + { + return Encoding.GetEncoding(charset.Replace("-", string.Empty)); + } + } + private async Task> GetReadableFile(string mediaPath, string[] inputFiles, MediaProtocol protocol, @@ -227,8 +244,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles // Convert var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, ".srt"); - await ConvertTextSubtitleToSrt(subtitleStream.Path, outputPath, subtitleStream.Language, cancellationToken) - .ConfigureAwait(false); + await ConvertTextSubtitleToSrt(subtitleStream.Path, outputPath, cancellationToken).ConfigureAwait(false); return new Tuple(outputPath, "srt", true); } @@ -321,11 +337,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// /// The input path. /// The output path. - /// The language. /// The cancellation token. /// Task. - public async Task ConvertTextSubtitleToSrt(string inputPath, string outputPath, string language, - CancellationToken cancellationToken) + public async Task ConvertTextSubtitleToSrt(string inputPath, string outputPath, CancellationToken cancellationToken) { var semaphore = GetLock(outputPath); @@ -335,7 +349,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { if (!File.Exists(outputPath)) { - await ConvertTextSubtitleToSrtInternal(inputPath, outputPath, language).ConfigureAwait(false); + await ConvertTextSubtitleToSrtInternal(inputPath, outputPath).ConfigureAwait(false); } } finally @@ -349,15 +363,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// /// The input path. /// The output path. - /// The language. /// Task. - /// - /// inputPath + /// inputPath /// or - /// outputPath - /// + /// outputPath /// - private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string outputPath, string language) + private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string outputPath) { if (string.IsNullOrEmpty(inputPath)) { @@ -371,9 +382,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - var encodingParam = string.IsNullOrEmpty(language) - ? string.Empty - : GetSubtitleFileCharacterSet(inputPath, language); + var encodingParam = GetSubtitleFileCharacterSet(inputPath); if (!string.IsNullOrEmpty(encodingParam)) { @@ -696,10 +705,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// Gets the subtitle language encoding param. /// /// The path. - /// The language. /// System.String. - public string GetSubtitleFileCharacterSet(string path, string language) + public string GetSubtitleFileCharacterSet(string path) { + if (GetFileEncoding(path).Equals(Encoding.UTF8)) + { + return string.Empty; + } + var charset = DetectCharset(path); if (!string.IsNullOrWhiteSpace(charset)) @@ -712,11 +725,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles return charset; } - if (GetFileEncoding(path).Equals(Encoding.UTF8)) - { - return string.Empty; - } + return null; + } + public string GetSubtitleFileCharacterSetFromLanguage(string language) + { switch (language.ToLower()) { case "pol": diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index e51cca770..a2a909dcc 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -191,8 +191,6 @@ namespace MediaBrowser.Model.Configuration public bool SaveMetadataHidden { get; set; } - public bool EnableWin8HttpListener { get; set; } - public NameValuePair[] ContentTypes { get; set; } public bool EnableAudioArchiveFiles { get; set; } @@ -214,7 +212,6 @@ namespace MediaBrowser.Model.Configuration EnableDashboardResourceMinification = true; EnableAutomaticRestart = true; - EnableWin8HttpListener = true; EnableUPnP = true; diff --git a/MediaBrowser.Providers/Movies/MovieDbSearch.cs b/MediaBrowser.Providers/Movies/MovieDbSearch.cs index ae176e489..f1ccd1c30 100644 --- a/MediaBrowser.Providers/Movies/MovieDbSearch.cs +++ b/MediaBrowser.Providers/Movies/MovieDbSearch.cs @@ -183,14 +183,7 @@ namespace MediaBrowser.Providers.Movies if (DateTime.TryParseExact(result.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r)) { // Allow one year tolernace, preserve order from Tmdb - var variance = Math.Abs(r.Year - year.Value); - - if (variance <= 1) - { - return 0; - } - - return variance; + return Math.Abs(r.Year - year.Value); } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 1d7e89d28..7022dc76d 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -41,8 +41,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer private readonly ReaderWriterLockSlim _localEndpointLock = new ReaderWriterLockSlim(); - private readonly bool _supportsNativeWebSocket; - private string _certificatePath; /// @@ -67,12 +65,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer ILogManager logManager, string serviceName, string defaultRedirectPath, - bool supportsNativeWebSocket, params Assembly[] assembliesWithServices) : base(serviceName, assembliesWithServices) { DefaultRedirectPath = defaultRedirectPath; - _supportsNativeWebSocket = supportsNativeWebSocket; _logger = logManager.GetLogger("HttpServer"); @@ -210,13 +206,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer private IHttpListener GetListener() { - if (_supportsNativeWebSocket && NativeWebSocket.IsSupported) - { - // Certificate location is ignored here. You need to use netsh - // to assign the certificate to the proper port. - return new HttpListenerServer(_logger, OnRequestReceived); - } - return new WebSocketSharpListener(_logger, OnRequestReceived, _certificatePath); } diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs index 73d761060..d1222ab74 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs @@ -17,17 +17,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// The log manager. /// Name of the server. /// The default redirectpath. - /// if set to true [supports native web socket]. /// IHttpServer. public static IHttpServer CreateServer(IApplicationHost applicationHost, ILogManager logManager, string serverName, - string defaultRedirectpath, - bool supportsNativeWebSocket) + string defaultRedirectpath) { LogManager.LogFactory = new ServerLogFactory(logManager); - return new HttpListenerHost(applicationHost, logManager, serverName, defaultRedirectpath, supportsNativeWebSocket); + return new HttpListenerHost(applicationHost, logManager, serverName, defaultRedirectpath); } } } diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index ad7a0aef0..5235f46a9 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -591,6 +591,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -625,6 +627,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 37948cb3f..dc74c5f86 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -42,7 +42,7 @@ "ButtonTermsOfService": "Terms of Service", "HeaderDeveloperOptions": "Developer Options", "OptionEnableWebClientResponseCache": "Enable web client response caching", - "OptionDisableForDevelopmentHelp": "Disable these for web client development purposes", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", "OptionEnableWebClientResourceMinification": "Enable web client resource minification", "LabelDashboardSourcePath": "Web client source path:", "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.", @@ -53,6 +53,7 @@ "HeaderAudio": "Audio", "HeaderVideo": "Video", "HeaderPaths": "Paths", + "TitleNotifications": "Notifications", "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", @@ -71,6 +72,7 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Setup your media library", "ButtonAddMediaFolder": "Add media folder", "LabelFolderType": "Folder type:", diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index e15b60d47..3867fc243 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -460,19 +460,7 @@ namespace MediaBrowser.Server.Startup.Common RegisterSingleInstance(() => new SearchEngine(LogManager, LibraryManager, UserManager)); - if (IsFirstRun) - { - ServerConfigurationManager.Configuration.EnableWin8HttpListener = false; - ServerConfigurationManager.SaveConfiguration(); - _supportsNativeWebSocket = false; - } - - if (!ServerConfigurationManager.Configuration.EnableWin8HttpListener) - { - _supportsNativeWebSocket = false; - } - - HttpServer = ServerFactory.CreateServer(this, LogManager, "Media Browser", "web/index.html", false); + HttpServer = ServerFactory.CreateServer(this, LogManager, "Media Browser", "web/index.html"); RegisterSingleInstance(HttpServer, false); progress.Report(10); -- cgit v1.2.3 From 1f1852f3cbe2a7899aea0d306a77d2eedb0434fc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 4 Feb 2015 22:01:37 -0500 Subject: sync updates --- MediaBrowser.Api/MediaBrowser.Api.csproj | 1 + MediaBrowser.Api/Sync/SyncJobWebSocketListener.cs | 120 +++++++++++++++++++++ MediaBrowser.Api/Sync/SyncService.cs | 4 +- .../Entities/UserViewBuilder.cs | 5 + .../MediaEncoding/EncodingJobOptions.cs | 7 +- MediaBrowser.Controller/Sync/ISyncManager.cs | 8 +- .../MediaBrowser.Model.Portable.csproj | 3 + .../MediaBrowser.Model.net35.csproj | 3 + MediaBrowser.Model/ApiClient/IApiClient.cs | 15 +++ MediaBrowser.Model/ApiClient/IServerEvents.cs | 4 + MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + MediaBrowser.Model/Sync/CompleteSyncJobInfo.cs | 15 +++ MediaBrowser.Model/Sync/SyncJobItemStatus.cs | 11 +- MediaBrowser.Model/Sync/SyncJobStatus.cs | 11 +- .../Dto/DtoService.cs | 3 +- .../Library/LibraryManager.cs | 5 + .../Localization/JavaScript/javascript.json | 5 +- .../Sync/SyncJobProcessor.cs | 55 ++++++---- .../Sync/SyncManager.cs | 47 ++++++-- .../Sync/SyncScheduledTask.cs | 2 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Model.Signed.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 24 files changed, 280 insertions(+), 57 deletions(-) create mode 100644 MediaBrowser.Api/Sync/SyncJobWebSocketListener.cs create mode 100644 MediaBrowser.Model/Sync/CompleteSyncJobInfo.cs (limited to 'MediaBrowser.Controller/MediaEncoding') diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 552091280..23cdf8b7a 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -130,6 +130,7 @@ + diff --git a/MediaBrowser.Api/Sync/SyncJobWebSocketListener.cs b/MediaBrowser.Api/Sync/SyncJobWebSocketListener.cs new file mode 100644 index 000000000..61a26d160 --- /dev/null +++ b/MediaBrowser.Api/Sync/SyncJobWebSocketListener.cs @@ -0,0 +1,120 @@ +using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Events; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Sync; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Sync +{ + /// + /// Class SessionInfoWebSocketListener + /// + class SyncJobWebSocketListener : BasePeriodicWebSocketListener + { + /// + /// Gets the name. + /// + /// The name. + protected override string Name + { + get { return "SyncJob"; } + } + + private readonly ISyncManager _syncManager; + private string _jobId; + + public SyncJobWebSocketListener(ILogger logger, ISyncManager syncManager) + : base(logger) + { + _syncManager = syncManager; + _syncManager.SyncJobCancelled += _syncManager_SyncJobCancelled; + _syncManager.SyncJobUpdated += _syncManager_SyncJobUpdated; + _syncManager.SyncJobItemCreated += _syncManager_SyncJobItemCreated; + _syncManager.SyncJobItemUpdated += _syncManager_SyncJobItemUpdated; + } + + void _syncManager_SyncJobItemUpdated(object sender, GenericEventArgs e) + { + if (string.Equals(e.Argument.Id, _jobId, StringComparison.Ordinal)) + { + SendData(false); + } + } + + void _syncManager_SyncJobItemCreated(object sender, GenericEventArgs e) + { + if (string.Equals(e.Argument.Id, _jobId, StringComparison.Ordinal)) + { + SendData(true); + } + } + + protected override void ParseMessageParams(string[] values) + { + base.ParseMessageParams(values); + + if (values.Length > 0) + { + _jobId = values[0]; + } + } + + void _syncManager_SyncJobUpdated(object sender, GenericEventArgs e) + { + if (string.Equals(e.Argument.Id, _jobId, StringComparison.Ordinal)) + { + SendData(false); + } + } + + void _syncManager_SyncJobCancelled(object sender, GenericEventArgs e) + { + if (string.Equals(e.Argument.Id, _jobId, StringComparison.Ordinal)) + { + SendData(true); + } + } + + /// + /// Gets the data to send. + /// + /// The state. + /// Task{SystemInfo}. + protected override Task GetDataToSend(WebSocketListenerState state) + { + var job = _syncManager.GetJob(_jobId); + var items = _syncManager.GetJobItems(new SyncJobItemQuery + { + AddMetadata = true, + JobId = _jobId + }); + + var info = new CompleteSyncJobInfo + { + Job = job, + JobItems = items.Items.ToList() + }; + + return Task.FromResult(info); + } + + protected override bool SendOnTimer + { + get + { + return false; + } + } + + protected override void Dispose(bool dispose) + { + _syncManager.SyncJobCancelled -= _syncManager_SyncJobCancelled; + _syncManager.SyncJobUpdated -= _syncManager_SyncJobUpdated; + + base.Dispose(dispose); + } + } +} diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs index 93d8a8d0a..13c716136 100644 --- a/MediaBrowser.Api/Sync/SyncService.cs +++ b/MediaBrowser.Api/Sync/SyncService.cs @@ -206,7 +206,7 @@ namespace MediaBrowser.Api.Sync { var jobItem = _syncManager.GetJobItem(request.Id); - if (jobItem.Status != SyncJobItemStatus.Transferring) + if (jobItem.Status < SyncJobItemStatus.ReadyToTransfer) { throw new ArgumentException("The job item is not yet ready for transfer."); } @@ -286,7 +286,7 @@ namespace MediaBrowser.Api.Sync { var jobItem = _syncManager.GetJobItem(request.Id); - if (jobItem.Status != SyncJobItemStatus.Transferring) + if (jobItem.Status < SyncJobItemStatus.ReadyToTransfer) { throw new ArgumentException("The job item is not yet ready for transfer."); } diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index a24a42535..318c5fff3 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -846,6 +846,11 @@ namespace MediaBrowser.Controller.Entities BaseItem queryParent, User user) { + if (items == null) + { + throw new ArgumentNullException("items"); + } + if (CollapseBoxSetItems(query, queryParent, user)) { items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index ad9ab90a0..fe0fb3295 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -81,12 +81,17 @@ namespace MediaBrowser.Controller.MediaEncoding VideoCodec = info.VideoCodec; VideoBitRate = info.VideoBitrate; AudioStreamIndex = info.AudioStreamIndex; - SubtitleStreamIndex = info.SubtitleStreamIndex; MaxRefFrames = info.MaxRefFrames; MaxVideoBitDepth = info.MaxVideoBitDepth; SubtitleMethod = info.SubtitleDeliveryMethod; Cabac = info.Cabac; Context = info.Context; + + if (info.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode || + info.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed) + { + SubtitleStreamIndex = info.SubtitleStreamIndex; + } } } } diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs index 362b9c3bc..dc15a394e 100644 --- a/MediaBrowser.Controller/Sync/ISyncManager.cs +++ b/MediaBrowser.Controller/Sync/ISyncManager.cs @@ -15,7 +15,9 @@ namespace MediaBrowser.Controller.Sync event EventHandler> SyncJobCreated; event EventHandler> SyncJobCancelled; event EventHandler> SyncJobUpdated; - + event EventHandler> SyncJobItemUpdated; + event EventHandler> SyncJobItemCreated; + /// /// Creates the job. /// @@ -35,7 +37,7 @@ namespace MediaBrowser.Controller.Sync /// The query. /// QueryResult<SyncJobItem>. QueryResult GetJobItems(SyncJobItemQuery query); - + /// /// Gets the job. /// @@ -63,7 +65,7 @@ namespace MediaBrowser.Controller.Sync /// The identifier. /// Task. Task CancelJobItem(string id); - + /// /// Cancels the job. /// diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 310170b5f..ba3065bc9 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -1043,6 +1043,9 @@ Session\UserDataChangeInfo.cs + + Sync\CompleteSyncJobInfo.cs + Sync\DeviceFileInfo.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 31d2e6470..8d22f25a9 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -1002,6 +1002,9 @@ Session\UserDataChangeInfo.cs + + Sync\CompleteSyncJobInfo.cs + Sync\DeviceFileInfo.cs diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 9fe138a49..a7d11d507 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -893,6 +893,21 @@ namespace MediaBrowser.Model.ApiClient /// if set to true [keep existing authentication]. void ChangeServerLocation(string address, bool keepExistingAuth = false); + /// + /// Starts the receiving synchronize job updates. + /// + /// The interval ms. + /// The job identifier. + /// Task. + Task StartReceivingSyncJobUpdates(int intervalMs, string jobId); + + /// + /// Stops the receiving synchronize job updates. + /// + /// The interval ms. + /// Task. + Task StopReceivingSyncJobUpdates(int intervalMs); + /// /// Starts the receiving synchronize jobs updates. /// diff --git a/MediaBrowser.Model/ApiClient/IServerEvents.cs b/MediaBrowser.Model/ApiClient/IServerEvents.cs index 311cb8b21..ae2d5d323 100644 --- a/MediaBrowser.Model/ApiClient/IServerEvents.cs +++ b/MediaBrowser.Model/ApiClient/IServerEvents.cs @@ -144,5 +144,9 @@ namespace MediaBrowser.Model.ApiClient /// Occurs when [synchronize jobs updated]. /// event EventHandler>> SyncJobsUpdated; + /// + /// Occurs when [synchronize job updated]. + /// + event EventHandler> SyncJobUpdated; } } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 0962cbe7a..c8e09dd82 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -368,6 +368,7 @@ + diff --git a/MediaBrowser.Model/Sync/CompleteSyncJobInfo.cs b/MediaBrowser.Model/Sync/CompleteSyncJobInfo.cs new file mode 100644 index 000000000..52d3fab3c --- /dev/null +++ b/MediaBrowser.Model/Sync/CompleteSyncJobInfo.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Model.Sync +{ + public class CompleteSyncJobInfo + { + public SyncJob Job { get; set; } + public List JobItems { get; set; } + + public CompleteSyncJobInfo() + { + JobItems = new List(); + } + } +} diff --git a/MediaBrowser.Model/Sync/SyncJobItemStatus.cs b/MediaBrowser.Model/Sync/SyncJobItemStatus.cs index 913f9e259..c4e23c63c 100644 --- a/MediaBrowser.Model/Sync/SyncJobItemStatus.cs +++ b/MediaBrowser.Model/Sync/SyncJobItemStatus.cs @@ -5,10 +5,11 @@ namespace MediaBrowser.Model.Sync { Queued = 0, Converting = 1, - Transferring = 2, - Synced = 3, - RemovedFromDevice = 4, - Failed = 5, - Cancelled = 6 + ReadyToTransfer = 2, + Transferring = 3, + Synced = 4, + RemovedFromDevice = 5, + Failed = 6, + Cancelled = 7 } } diff --git a/MediaBrowser.Model/Sync/SyncJobStatus.cs b/MediaBrowser.Model/Sync/SyncJobStatus.cs index 6c0068a8a..ac211a32a 100644 --- a/MediaBrowser.Model/Sync/SyncJobStatus.cs +++ b/MediaBrowser.Model/Sync/SyncJobStatus.cs @@ -5,10 +5,11 @@ namespace MediaBrowser.Model.Sync { Queued = 0, Converting = 1, - Transferring = 2, - Completed = 3, - CompletedWithError = 4, - Failed = 5, - Cancelled = 6 + ReadyToTransfer = 2, + Transferring = 3, + Completed = 4, + CompletedWithError = 5, + Failed = 6, + Cancelled = 7 } } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 61c24cf54..7b36321f1 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -162,7 +162,8 @@ namespace MediaBrowser.Server.Implementations.Dto { SyncJobItemStatus.Converting, SyncJobItemStatus.Queued, - SyncJobItemStatus.Transferring + SyncJobItemStatus.Transferring, + SyncJobItemStatus.ReadyToTransfer } }); diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index d7ea444a3..29871d928 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -517,6 +517,11 @@ namespace MediaBrowser.Server.Implementations.Library public IEnumerable ReplaceVideosWithPrimaryVersions(IEnumerable items) { + if (items == null) + { + throw new ArgumentNullException("items"); + } + var dict = new Dictionary(); foreach (var item in items) diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index 5e881e3b6..3fddf274c 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -53,6 +53,7 @@ "SyncJobStatusFailed": "Failed", "SyncJobStatusCancelled": "Cancelled", "SyncJobStatusCompleted": "Synced", + "SyncJobStatusReadyToTransfer": "Ready to Transfer", "SyncJobStatusTransferring": "Transferring", "SyncJobStatusCompletedWithError": "Synced with errors", "LabelCollection": "Collection", @@ -216,8 +217,8 @@ "MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?", "MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?", "ButtonUpdateNow": "Update Now", - "ValueItemCount": "{0} item", - "ValueItemCountPlural": "{0} items", + "ValueItemCount": "{0} item", + "ValueItemCountPlural": "{0} items", "NewVersionOfSomethingAvailable": "A new version of {0} is available!", "VersionXIsAvailableForDownload": "Version {0} is now available for download.", "LabelVersionNumber": "Version {0}", diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index c373faf1e..e418448db 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -29,7 +29,7 @@ namespace MediaBrowser.Server.Implementations.Sync { private readonly ILibraryManager _libraryManager; private readonly ISyncRepository _syncRepo; - private readonly ISyncManager _syncManager; + private readonly SyncManager _syncManager; private readonly ILogger _logger; private readonly IUserManager _userManager; private readonly ITVSeriesManager _tvSeriesManager; @@ -38,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.Sync private readonly IConfigurationManager _config; private readonly IFileSystem _fileSystem; - public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem) + public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, SyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem) { _libraryManager = libraryManager; _syncRepo = syncRepo; @@ -106,6 +106,7 @@ namespace MediaBrowser.Server.Implementations.Sync }; await _syncRepo.Create(jobItem).ConfigureAwait(false); + _syncManager.OnSyncJobItemCreated(jobItem); jobItems.Add(jobItem); } @@ -184,11 +185,19 @@ namespace MediaBrowser.Server.Implementations.Sync { job.Status = SyncJobStatus.Cancelled; } + else if (jobItems.All(i => i.Status == SyncJobItemStatus.ReadyToTransfer)) + { + job.Status = SyncJobStatus.ReadyToTransfer; + } + else if (jobItems.All(i => i.Status == SyncJobItemStatus.Transferring)) + { + job.Status = SyncJobStatus.Transferring; + } else if (jobItems.Any(i => i.Status == SyncJobItemStatus.Converting)) { job.Status = SyncJobStatus.Converting; } - else if (pct >= 100) + else if (jobItems.All(i => i.Status == SyncJobItemStatus.Cancelled || i.Status == SyncJobItemStatus.Failed || i.Status == SyncJobItemStatus.Synced || i.Status == SyncJobItemStatus.RemovedFromDevice)) { if (jobItems.Any(i => i.Status == SyncJobItemStatus.Failed)) { @@ -201,12 +210,12 @@ namespace MediaBrowser.Server.Implementations.Sync } else { - job.Status = SyncJobStatus.Transferring; + job.Status = SyncJobStatus.Queued; } await _syncRepo.Update(job).ConfigureAwait(false); - ((SyncManager)_syncManager).OnSyncJobUpdated(job); + _syncManager.OnSyncJobUpdated(job); } public async Task> GetItemsForSync(SyncCategory? category, string parentId, IEnumerable itemIds, User user, bool unwatchedOnly) @@ -414,7 +423,7 @@ namespace MediaBrowser.Server.Implementations.Sync { jobItem.Status = SyncJobItemStatus.Failed; _logger.Error("Unable to locate library item for JobItem {0}, ItemId {1}", jobItem.Id, jobItem.ItemId); - await _syncRepo.Update(jobItem).ConfigureAwait(false); + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); return; } @@ -423,7 +432,7 @@ namespace MediaBrowser.Server.Implementations.Sync { jobItem.Status = SyncJobItemStatus.Failed; _logger.Error("Unable to locate SyncTarget for JobItem {0}, SyncTargetId {1}", jobItem.Id, jobItem.TargetId); - await _syncRepo.Update(jobItem).ConfigureAwait(false); + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); return; } @@ -490,7 +499,7 @@ namespace MediaBrowser.Server.Implementations.Sync if (streamInfo.PlayMethod == PlayMethod.Transcode) { // Save the job item now since conversion could take a while - await _syncRepo.Update(jobItem).ConfigureAwait(false); + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); await UpdateJobStatus(job).ConfigureAwait(false); try @@ -504,7 +513,7 @@ namespace MediaBrowser.Server.Implementations.Sync if ((DateTime.UtcNow - lastJobUpdate).TotalSeconds >= DatabaseProgressUpdateIntervalSeconds) { jobItem.Progress = pct / 2; - await _syncRepo.Update(jobItem).ConfigureAwait(false); + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); await UpdateJobStatus(job).ConfigureAwait(false); } }); @@ -528,7 +537,7 @@ namespace MediaBrowser.Server.Implementations.Sync if (jobItem.Status == SyncJobItemStatus.Failed || jobItem.Status == SyncJobItemStatus.Queued) { - await _syncRepo.Update(jobItem).ConfigureAwait(false); + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); return; } @@ -555,14 +564,14 @@ namespace MediaBrowser.Server.Implementations.Sync if (externalSubs.Count > 0) { // Save the job item now since conversion could take a while - await _syncRepo.Update(jobItem).ConfigureAwait(false); + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); await ConvertSubtitles(jobItem, externalSubs, streamInfo, cancellationToken).ConfigureAwait(false); } jobItem.Progress = 50; - jobItem.Status = SyncJobItemStatus.Transferring; - await _syncRepo.Update(jobItem).ConfigureAwait(false); + jobItem.Status = SyncJobItemStatus.ReadyToTransfer; + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); } private bool RequiresExtraction(SubtitleStreamInfo stream, MediaSourceInfo mediaSource) @@ -666,7 +675,7 @@ namespace MediaBrowser.Server.Implementations.Sync } jobItem.Status = SyncJobItemStatus.Converting; - await _syncRepo.Update(jobItem).ConfigureAwait(false); + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); await UpdateJobStatus(job).ConfigureAwait(false); try @@ -680,7 +689,7 @@ namespace MediaBrowser.Server.Implementations.Sync if ((DateTime.UtcNow - lastJobUpdate).TotalSeconds >= DatabaseProgressUpdateIntervalSeconds) { jobItem.Progress = pct / 2; - await _syncRepo.Update(jobItem).ConfigureAwait(false); + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); await UpdateJobStatus(job).ConfigureAwait(false); } }); @@ -704,7 +713,7 @@ namespace MediaBrowser.Server.Implementations.Sync if (jobItem.Status == SyncJobItemStatus.Failed || jobItem.Status == SyncJobItemStatus.Queued) { - await _syncRepo.Update(jobItem).ConfigureAwait(false); + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); return; } @@ -729,8 +738,8 @@ namespace MediaBrowser.Server.Implementations.Sync } jobItem.Progress = 50; - jobItem.Status = SyncJobItemStatus.Transferring; - await _syncRepo.Update(jobItem).ConfigureAwait(false); + jobItem.Status = SyncJobItemStatus.ReadyToTransfer; + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); } private async Task Sync(SyncJobItem jobItem, Photo item, DeviceProfile profile, CancellationToken cancellationToken) @@ -738,17 +747,17 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.OutputPath = item.Path; jobItem.Progress = 50; - jobItem.Status = SyncJobItemStatus.Transferring; - await _syncRepo.Update(jobItem).ConfigureAwait(false); + jobItem.Status = SyncJobItemStatus.ReadyToTransfer; + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); } private async Task SyncGeneric(SyncJobItem jobItem, BaseItem item, CancellationToken cancellationToken) { jobItem.OutputPath = item.Path; - + jobItem.Progress = 50; - jobItem.Status = SyncJobItemStatus.Transferring; - await _syncRepo.Update(jobItem).ConfigureAwait(false); + jobItem.Status = SyncJobItemStatus.ReadyToTransfer; + await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); } private async Task DownloadFile(SyncJobItem jobItem, MediaSourceInfo mediaSource, CancellationToken cancellationToken) diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index 6eef268b9..eecbd78d1 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -52,6 +52,8 @@ namespace MediaBrowser.Server.Implementations.Sync public event EventHandler> SyncJobCreated; public event EventHandler> SyncJobCancelled; public event EventHandler> SyncJobUpdated; + public event EventHandler> SyncJobItemUpdated; + public event EventHandler> SyncJobItemCreated; public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func dtoService, IApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func mediaEncoder, IFileSystem fileSystem, Func subtitleEncoder, IConfigurationManager config) { @@ -202,6 +204,32 @@ namespace MediaBrowser.Server.Implementations.Sync } } + internal async Task UpdateSyncJobItemInternal(SyncJobItem jobItem) + { + await _repo.Update(jobItem).ConfigureAwait(false); + + if (SyncJobUpdated != null) + { + EventHelper.FireEventIfNotNull(SyncJobItemUpdated, this, new GenericEventArgs + { + Argument = jobItem + + }, _logger); + } + } + + internal void OnSyncJobItemCreated(SyncJobItem job) + { + if (SyncJobUpdated != null) + { + EventHelper.FireEventIfNotNull(SyncJobItemCreated, this, new GenericEventArgs + { + Argument = job + + }, _logger); + } + } + public async Task> GetJobs(SyncJobQuery query) { var result = _repo.GetJobs(query); @@ -504,7 +532,7 @@ namespace MediaBrowser.Server.Implementations.Sync } } - await _repo.Update(jobItem).ConfigureAwait(false); + await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); var processor = GetSyncJobProcessor(); @@ -610,7 +638,10 @@ namespace MediaBrowser.Server.Implementations.Sync var jobItemResult = GetJobItems(new SyncJobItemQuery { TargetId = targetId, - Statuses = new List { SyncJobItemStatus.Transferring } + Statuses = new List + { + SyncJobItemStatus.ReadyToTransfer + } }); return jobItemResult.Items @@ -669,7 +700,7 @@ namespace MediaBrowser.Server.Implementations.Sync { // Content is no longer on the device jobItem.Status = SyncJobItemStatus.RemovedFromDevice; - await _repo.Update(jobItem).ConfigureAwait(false); + await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); } } @@ -761,7 +792,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Progress = 0; jobItem.IsMarkedForRemoval = false; - await _repo.Update(jobItem).ConfigureAwait(false); + await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); var processor = GetSyncJobProcessor(); @@ -772,7 +803,7 @@ namespace MediaBrowser.Server.Implementations.Sync { var jobItem = _repo.GetJobItem(id); - if (jobItem.Status != SyncJobItemStatus.Queued && jobItem.Status != SyncJobItemStatus.Transferring && jobItem.Status != SyncJobItemStatus.Converting) + if (jobItem.Status != SyncJobItemStatus.Queued && jobItem.Status != SyncJobItemStatus.ReadyToTransfer && jobItem.Status != SyncJobItemStatus.Converting) { throw new ArgumentException("Operation is not valid for this job item"); } @@ -781,7 +812,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Progress = 0; jobItem.IsMarkedForRemoval = true; - await _repo.Update(jobItem).ConfigureAwait(false); + await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); var processor = GetSyncJobProcessor(); @@ -814,7 +845,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.IsMarkedForRemoval = true; - await _repo.Update(jobItem).ConfigureAwait(false); + await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); var processor = GetSyncJobProcessor(); @@ -832,7 +863,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.IsMarkedForRemoval = false; - await _repo.Update(jobItem).ConfigureAwait(false); + await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); var processor = GetSyncJobProcessor(); diff --git a/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs b/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs index b68a97817..ccc9508e8 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs @@ -60,7 +60,7 @@ namespace MediaBrowser.Server.Implementations.Sync public Task Execute(CancellationToken cancellationToken, IProgress progress) { - return new SyncJobProcessor(_libraryManager, _syncRepo, _syncManager, _logger, _userManager, _tvSeriesManager, _mediaEncoder, _subtitleEncoder, _config, _fileSystem) + return new SyncJobProcessor(_libraryManager, _syncRepo, (SyncManager)_syncManager, _logger, _userManager, _tvSeriesManager, _mediaEncoder, _subtitleEncoder, _config, _fileSystem) .Sync(progress, cancellationToken); } diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 4b104fe25..1a65fba67 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.559 + 3.0.560 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 40a395a63..d28f98aff 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.559 + 3.0.560 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index 17597b582..d4b030ba1 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.559 + 3.0.560 MediaBrowser.Model - Signed Edition Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index c9a635f64..e5b7a27ba 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.559 + 3.0.560 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - + -- cgit v1.2.3 From 9110d23710980eecc112753af46f7fcda7558364 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 7 Feb 2015 16:03:09 -0500 Subject: added SupportsExternalStream to MediaStream --- MediaBrowser.Controller/Entities/Audio/Audio.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 1 + MediaBrowser.Controller/Entities/Video.cs | 7 +-- .../Library/IMediaSourceManager.cs | 11 +++++ .../MediaBrowser.Controller.csproj | 1 + .../MediaEncoding/MediaStreamSelector.cs | 12 +++-- MediaBrowser.Model/Dlna/StreamBuilder.cs | 7 ++- MediaBrowser.Model/Entities/MediaStream.cs | 8 +++- .../Subtitles/SubtitleManager.cs | 8 ++-- .../Library/MediaSourceManager.cs | 51 ++++++++++++++++++++++ .../MediaBrowser.Server.Implementations.csproj | 1 + .../Session/SessionManager.cs | 8 ++-- .../Sync/SyncJobProcessor.cs | 3 +- .../ApplicationHost.cs | 9 +++- 14 files changed, 108 insertions(+), 21 deletions(-) create mode 100644 MediaBrowser.Controller/Library/IMediaSourceManager.cs create mode 100644 MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs (limited to 'MediaBrowser.Controller/MediaEncoding') diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index a7b91b868..902447999 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 = ItemRepository.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(), + MediaStreams = MediaSourceManager.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(), Name = i.Name, Path = enablePathSubstituion ? GetMappedPath(i.Path, locationType) : i.Path, RunTimeTicks = i.RunTimeTicks, diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 1443d99d3..1379ba829 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -300,6 +300,7 @@ namespace MediaBrowser.Controller.Entities public static IChannelManager ChannelManager { get; set; } public static ICollectionManager CollectionManager { get; set; } public static IImageProcessor ImageProcessor { get; set; } + public static IMediaSourceManager MediaSourceManager { get; set; } /// /// Returns a that represents this instance. diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 12c377c90..d4507bc33 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -422,7 +422,7 @@ namespace MediaBrowser.Controller.Entities public virtual IEnumerable GetMediaStreams() { - return ItemRepository.GetMediaStreams(new MediaStreamQuery + return MediaSourceManager.GetMediaStreams(new MediaStreamQuery { ItemId = Id }); @@ -435,7 +435,7 @@ namespace MediaBrowser.Controller.Entities return null; } - return ItemRepository.GetMediaStreams(new MediaStreamQuery + return MediaSourceManager.GetMediaStreams(new MediaStreamQuery { ItemId = Id, Index = DefaultVideoStreamIndex.Value @@ -474,7 +474,8 @@ namespace MediaBrowser.Controller.Entities private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video i, MediaSourceType type) { - var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(); + var mediaStreams = MediaSourceManager.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }) + .ToList(); var locationType = i.LocationType; diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs new file mode 100644 index 000000000..4378bc85d --- /dev/null +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -0,0 +1,11 @@ +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Entities; +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Library +{ + public interface IMediaSourceManager + { + IEnumerable GetMediaStreams(MediaStreamQuery query); + } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 27beabcc1..e9531e057 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -170,6 +170,7 @@ + diff --git a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs index b18651a68..57fddb2b1 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs @@ -90,10 +90,16 @@ namespace MediaBrowser.Controller.MediaEncoding return index == -1 ? 100 : index; }) - .ThenBy(i => i.IsDefault) - .ThenBy(i => i.IsTextSubtitleStream) - .ThenBy(i => i.IsExternal) + .ThenBy(i => GetBooleanOrderBy(i.IsDefault)) + .ThenBy(i => GetBooleanOrderBy(i.SupportsExternalStream)) + .ThenBy(i => GetBooleanOrderBy(i.IsTextSubtitleStream)) + .ThenBy(i => GetBooleanOrderBy(i.IsExternal)) .ThenBy(i => i.Index); } + + private static int GetBooleanOrderBy(bool value) + { + return value ? 0 : 1; + } } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 6076637b4..6fa29a533 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -543,9 +543,12 @@ namespace MediaBrowser.Model.Dlna // Look for an external profile that matches the stream type (text/graphical) foreach (SubtitleProfile profile in deviceProfile.SubtitleProfiles) { - if (profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format)) + if (subtitleStream.SupportsExternalStream) { - return profile; + if (profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format)) + { + return profile; + } } } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index db4a68cff..4af32bb50 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Model.Entities /// /// The reference frames. public int? RefFrames { get; set; } - + /// /// Gets or sets the length of the packet. /// @@ -156,6 +156,12 @@ namespace MediaBrowser.Model.Entities !StringHelper.EqualsIgnoreCase(codec, "sub"); } + /// + /// Gets or sets a value indicating whether [supports external stream]. + /// + /// true if [supports external stream]; otherwise, false. + public bool SupportsExternalStream { get; set; } + /// /// Gets or sets the filename. /// diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 187f8814b..c449edd07 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -27,18 +27,18 @@ namespace MediaBrowser.Providers.Subtitles private readonly IFileSystem _fileSystem; private readonly ILibraryMonitor _monitor; private readonly ILibraryManager _libraryManager; - private readonly IItemRepository _itemRepo; + private readonly IMediaSourceManager _mediaSourceManager; public event EventHandler SubtitlesDownloaded; public event EventHandler SubtitleDownloadFailure; - public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, ILibraryManager libraryManager, IItemRepository itemRepo) + public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager) { _logger = logger; _fileSystem = fileSystem; _monitor = monitor; _libraryManager = libraryManager; - _itemRepo = itemRepo; + _mediaSourceManager = mediaSourceManager; } public void AddParts(IEnumerable subtitleProviders) @@ -232,7 +232,7 @@ namespace MediaBrowser.Providers.Subtitles public Task DeleteSubtitles(string itemId, int index) { - var stream = _itemRepo.GetMediaStreams(new MediaStreamQuery + var stream = _mediaSourceManager.GetMediaStreams(new MediaStreamQuery { Index = index, ItemId = new Guid(itemId), diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs new file mode 100644 index 000000000..a45757d13 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -0,0 +1,51 @@ +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Entities; +using System.Collections.Generic; +using System.Linq; + +namespace MediaBrowser.Server.Implementations.Library +{ + public class MediaSourceManager : IMediaSourceManager + { + private readonly IItemRepository _itemRepo; + + public MediaSourceManager(IItemRepository itemRepo) + { + _itemRepo = itemRepo; + } + + public IEnumerable GetMediaStreams(MediaStreamQuery query) + { + var list = _itemRepo.GetMediaStreams(query) + .ToList(); + + foreach (var stream in list) + { + stream.SupportsExternalStream = StreamSupportsExternalStream(stream); + } + + return list; + } + + private bool StreamSupportsExternalStream(MediaStream stream) + { + if (stream.IsExternal) + { + return true; + } + + if (stream.IsTextSubtitleStream) + { + return InternalTextStreamSupportsExternalStream(stream); + } + + return false; + } + + private bool InternalTextStreamSupportsExternalStream(MediaStream stream) + { + return true; + } + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index bf11e4ef6..ce77b3db1 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -185,6 +185,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 6166e3d65..308f46c23 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -56,7 +56,7 @@ namespace MediaBrowser.Server.Implementations.Session private readonly IMusicManager _musicManager; private readonly IDtoService _dtoService; private readonly IImageProcessor _imageProcessor; - private readonly IItemRepository _itemRepo; + private readonly IMediaSourceManager _mediaSourceManager; private readonly IHttpClient _httpClient; private readonly IJsonSerializer _jsonSerializer; @@ -97,7 +97,7 @@ namespace MediaBrowser.Server.Implementations.Session private readonly SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1); - public SessionManager(IUserDataManager userDataRepository, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo, IDeviceManager deviceManager) + public SessionManager(IUserDataManager userDataRepository, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager) { _userDataRepository = userDataRepository; _logger = logger; @@ -107,12 +107,12 @@ namespace MediaBrowser.Server.Implementations.Session _musicManager = musicManager; _dtoService = dtoService; _imageProcessor = imageProcessor; - _itemRepo = itemRepo; _jsonSerializer = jsonSerializer; _appHost = appHost; _httpClient = httpClient; _authRepo = authRepo; _deviceManager = deviceManager; + _mediaSourceManager = mediaSourceManager; _deviceManager.DeviceOptionsUpdated += _deviceManager_DeviceOptionsUpdated; } @@ -1560,7 +1560,7 @@ namespace MediaBrowser.Server.Implementations.Session if (!string.IsNullOrWhiteSpace(mediaSourceId)) { - info.MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery + info.MediaStreams = _mediaSourceManager.GetMediaStreams(new MediaStreamQuery { ItemId = new Guid(mediaSourceId) diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index c299bf155..e9d9dc46f 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -616,7 +616,8 @@ namespace MediaBrowser.Server.Implementations.Sync IsForced = subtitle.IsForced, IsExternal = true, Language = subtitle.Language, - Path = fileInfo.Path + Path = fileInfo.Path, + SupportsExternalStream = true }); startingIndex++; diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 0bf9b9142..08c32204f 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -196,6 +196,7 @@ namespace MediaBrowser.Server.Startup.Common private ISyncRepository SyncRepository { get; set; } private ITVSeriesManager TVSeriesManager { get; set; } private ICollectionManager CollectionManager { get; set; } + private IMediaSourceManager MediaSourceManager { get; set; } private readonly StartupOptions _startupOptions; private readonly string _remotePackageName; @@ -459,7 +460,10 @@ namespace MediaBrowser.Server.Startup.Common DeviceManager = new DeviceManager(new DeviceRepository(ApplicationPaths, JsonSerializer, Logger, FileSystemManager), UserManager, FileSystemManager, LibraryMonitor, ConfigurationManager, LogManager.GetLogger("DeviceManager")); RegisterSingleInstance(DeviceManager); - SessionManager = new SessionManager(UserDataManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager); + MediaSourceManager = new MediaSourceManager(ItemRepository); + RegisterSingleInstance(MediaSourceManager); + + SessionManager = new SessionManager(UserDataManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager, MediaSourceManager); RegisterSingleInstance(SessionManager); var newsService = new Implementations.News.NewsService(ApplicationPaths, JsonSerializer); @@ -503,7 +507,7 @@ namespace MediaBrowser.Server.Startup.Common NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager); RegisterSingleInstance(NotificationManager); - SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, ItemRepository); + SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager); RegisterSingleInstance(SubtitleManager); ChapterManager = new ChapterManager(LibraryManager, LogManager.GetLogger("ChapterManager"), ServerConfigurationManager, ItemRepository); @@ -696,6 +700,7 @@ namespace MediaBrowser.Server.Startup.Common Folder.UserViewManager = UserViewManager; UserView.TVSeriesManager = TVSeriesManager; BaseItem.CollectionManager = CollectionManager; + BaseItem.MediaSourceManager = MediaSourceManager; } /// -- cgit v1.2.3