From 699bdacebc94635f129d3e68cfaaa49ebc0ff6f6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 31 Aug 2016 17:07:02 -0400 Subject: add setting to hide external content from suggestions --- MediaBrowser.Api/Library/LibraryService.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Api/Library') diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 14a771db03..c6b637f015 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -25,6 +25,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Controller.Configuration; namespace MediaBrowser.Api.Library { @@ -288,12 +289,13 @@ namespace MediaBrowser.Api.Library private readonly ITVSeriesManager _tvManager; private readonly ILibraryMonitor _libraryMonitor; private readonly IFileSystem _fileSystem; + private readonly IServerConfigurationManager _config; /// /// Initializes a new instance of the class. /// public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager, - IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem) + IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem, IServerConfigurationManager config) { _itemRepo = itemRepo; _libraryManager = libraryManager; @@ -307,6 +309,7 @@ namespace MediaBrowser.Api.Library _tvManager = tvManager; _libraryMonitor = libraryMonitor; _fileSystem = fileSystem; + _config = config; } public object Get(GetSimilarItems request) @@ -377,7 +380,7 @@ namespace MediaBrowser.Api.Library if (item is Movie || (program != null && program.IsMovie) || item is Trailer) { - return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService) + return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _config) { AuthorizationContext = AuthorizationContext, Logger = Logger, -- cgit v1.2.3 From 8b096ccc0e87883655bcf9ea1f9e22e9961450d3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 23 Sep 2016 02:21:54 -0400 Subject: stub out storage for new path substitution --- .../Library/LibraryStructureService.cs | 20 ++- MediaBrowser.Controller/Entities/Audio/Audio.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 4 +- .../Entities/CollectionFolder.cs | 31 +++-- MediaBrowser.Controller/Entities/Video.cs | 2 +- MediaBrowser.Controller/Library/ILibraryManager.cs | 6 +- MediaBrowser.Model/Configuration/LibraryOptions.cs | 8 ++ .../Dto/DtoService.cs | 4 +- .../Library/CoreResolutionIgnoreRule.cs | 3 +- .../Library/LibraryManager.cs | 140 ++++++++++++++------- .../LiveTv/EmbyTV/EmbyTV.cs | 8 +- 11 files changed, 160 insertions(+), 68 deletions(-) (limited to 'MediaBrowser.Api/Library') diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index 72966a7cdc..0ed4ee2a2d 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -112,6 +112,8 @@ namespace MediaBrowser.Api.Library /// The name. public string Path { get; set; } + public MediaPathInfo PathInfo { get; set; } + /// /// Gets or sets a value indicating whether [refresh library]. /// @@ -212,7 +214,12 @@ namespace MediaBrowser.Api.Library { var libraryOptions = request.LibraryOptions ?? new LibraryOptions(); - _libraryManager.AddVirtualFolder(request.Name, request.CollectionType, request.Paths, libraryOptions, request.RefreshLibrary); + if (request.Paths != null && request.Paths.Length > 0) + { + libraryOptions.PathInfos = request.Paths.Select(i => new MediaPathInfo { Path = i }).ToArray(); + } + + _libraryManager.AddVirtualFolder(request.Name, request.CollectionType, libraryOptions, request.RefreshLibrary); } /// @@ -308,7 +315,16 @@ namespace MediaBrowser.Api.Library try { - _libraryManager.AddMediaPath(request.Name, request.Path); + var mediaPath = request.PathInfo; + + if (mediaPath == null) + { + mediaPath = new MediaPathInfo + { + Path = request.Path + }; + } + _libraryManager.AddMediaPath(request.Name, mediaPath); } finally { diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 1af55a389f..599e72314d 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -262,7 +262,7 @@ namespace MediaBrowser.Controller.Entities.Audio Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File, MediaStreams = MediaSourceManager.GetMediaStreams(i.Id).ToList(), Name = i.Name, - Path = enablePathSubstituion ? GetMappedPath(i.Path, locationType) : i.Path, + Path = enablePathSubstituion ? GetMappedPath(i, i.Path, locationType) : i.Path, RunTimeTicks = i.RunTimeTicks, Container = i.Container, Size = i.Size diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 6e0a336207..30e0f3ee72 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2121,11 +2121,11 @@ namespace MediaBrowser.Controller.Entities return hasChanges; } - protected static string GetMappedPath(string path, LocationType locationType) + protected static string GetMappedPath(BaseItem item, string path, LocationType locationType) { if (locationType == LocationType.FileSystem || locationType == LocationType.Offline) { - return LibraryManager.GetPathAfterNetworkSubstitution(path); + return LibraryManager.GetPathAfterNetworkSubstitution(path, item); } return path; diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 30ea26eb66..77d7ca7f20 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -48,24 +48,14 @@ namespace MediaBrowser.Controller.Entities private static readonly Dictionary LibraryOptions = new Dictionary(); public LibraryOptions GetLibraryOptions() { - lock (LibraryOptions) - { - LibraryOptions options; - if (!LibraryOptions.TryGetValue(Path, out options)) - { - options = LoadLibraryOptions(); - LibraryOptions[Path] = options; - } - - return options; - } + return GetLibraryOptions(Path); } - private LibraryOptions LoadLibraryOptions() + private static LibraryOptions LoadLibraryOptions(string path) { try { - var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(Path)) as LibraryOptions; + var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(path)) as LibraryOptions; if (result == null) { @@ -100,6 +90,21 @@ namespace MediaBrowser.Controller.Entities SaveLibraryOptions(Path, options); } + public static LibraryOptions GetLibraryOptions(string path) + { + lock (LibraryOptions) + { + LibraryOptions options; + if (!LibraryOptions.TryGetValue(path, out options)) + { + options = LoadLibraryOptions(path); + LibraryOptions[path] = options; + } + + return options; + } + } + public static void SaveLibraryOptions(string path, LibraryOptions options) { lock (LibraryOptions) diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 8809f155c3..1406a05cef 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -600,7 +600,7 @@ namespace MediaBrowser.Controller.Entities Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File, MediaStreams = mediaStreams, Name = GetMediaSourceName(i, mediaStreams), - Path = enablePathSubstitution ? GetMappedPath(i.Path, locationType) : i.Path, + Path = enablePathSubstitution ? GetMappedPath(i, i.Path, locationType) : i.Path, RunTimeTicks = i.RunTimeTicks, Video3DFormat = i.Video3DFormat, VideoType = i.VideoType, diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index d5c2fcd20c..184a245c14 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -506,7 +506,7 @@ namespace MediaBrowser.Controller.Library /// QueryResult<BaseItem>. QueryResult QueryItems(InternalItemsQuery query); - string GetPathAfterNetworkSubstitution(string path); + string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem = null); /// /// Substitutes the path. @@ -556,9 +556,9 @@ namespace MediaBrowser.Controller.Library /// true if XXXX, false otherwise. bool IgnoreFile(FileSystemMetadata file, BaseItem parent); - void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, LibraryOptions options, bool refreshLibrary); + void AddVirtualFolder(string name, string collectionType, LibraryOptions options, bool refreshLibrary); void RemoveVirtualFolder(string name, bool refreshLibrary); - void AddMediaPath(string virtualFolderName, string path); + void AddMediaPath(string virtualFolderName, MediaPathInfo path); void RemoveMediaPath(string virtualFolderName, string path); QueryResult> GetGenres(InternalItemsQuery query); diff --git a/MediaBrowser.Model/Configuration/LibraryOptions.cs b/MediaBrowser.Model/Configuration/LibraryOptions.cs index 770ad433d6..460ee0918f 100644 --- a/MediaBrowser.Model/Configuration/LibraryOptions.cs +++ b/MediaBrowser.Model/Configuration/LibraryOptions.cs @@ -9,11 +9,19 @@ public bool EnableChapterImageExtraction { get; set; } public bool ExtractChapterImagesDuringLibraryScan { get; set; } public bool DownloadImagesInAdvance { get; set; } + public MediaPathInfo[] PathInfos { get; set; } public LibraryOptions() { EnablePhotos = true; EnableRealtimeMonitor = true; + PathInfos = new MediaPathInfo[] { }; } } + + public class MediaPathInfo + { + public string Path { get; set; } + public string NetworkPath { get; set; } + } } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index ae676626db..e4f1460c66 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1509,7 +1509,7 @@ namespace MediaBrowser.Server.Implementations.Dto } } - private string GetMappedPath(IHasMetadata item) + private string GetMappedPath(BaseItem item) { var path = item.Path; @@ -1517,7 +1517,7 @@ namespace MediaBrowser.Server.Implementations.Dto if (locationType == LocationType.FileSystem || locationType == LocationType.Offline) { - path = _libraryManager.GetPathAfterNetworkSubstitution(path); + path = _libraryManager.GetPathAfterNetworkSubstitution(path, item); } return path; diff --git a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index ba7e33890a..b550d1dda2 100644 --- a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -33,7 +33,8 @@ namespace MediaBrowser.Server.Implementations.Library // Synology "@eaDir", - "eaDir" + "eaDir", + "#recycle" }; diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 1f8c779539..cef0022cfc 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -2527,8 +2527,29 @@ namespace MediaBrowser.Server.Implementations.Library }).OrderBy(i => i.Path).ToList(); } - public string GetPathAfterNetworkSubstitution(string path) + public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem) { + if (ownerItem != null) + { + var libraryOptions = GetLibraryOptions(ownerItem); + if (libraryOptions != null) + { + foreach (var pathInfo in libraryOptions.PathInfos) + { + if (string.IsNullOrWhiteSpace(pathInfo.NetworkPath)) + { + continue; + } + + var substitutionResult = SubstitutePathInternal(path, pathInfo.Path, pathInfo.NetworkPath); + if (substitutionResult.Item2) + { + return substitutionResult.Item1; + } + } + } + } + foreach (var map in ConfigurationManager.Configuration.PathSubstitutions) { path = SubstitutePath(path, map.From, map.To); @@ -2538,6 +2559,11 @@ namespace MediaBrowser.Server.Implementations.Library } public string SubstitutePath(string path, string from, string to) + { + return SubstitutePathInternal(path, from, to).Item1; + } + + private Tuple SubstitutePathInternal(string path, string from, string to) { if (string.IsNullOrWhiteSpace(path)) { @@ -2552,7 +2578,11 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentNullException("to"); } - var newPath = path.Replace(from.Trim(), to.Trim(), StringComparison.OrdinalIgnoreCase); + from = from.Trim(); + to = to.Trim(); + + var newPath = path.Replace(from, to, StringComparison.OrdinalIgnoreCase); + var changed = false; if (!string.Equals(newPath, path)) { @@ -2564,9 +2594,11 @@ namespace MediaBrowser.Server.Implementations.Library { newPath = newPath.Replace('/', '\\'); } + + changed = true; } - return newPath; + return new Tuple(newPath, changed); } private void SetExtraTypeFromFilename(Video item) @@ -2695,7 +2727,7 @@ namespace MediaBrowser.Server.Implementations.Library throw new InvalidOperationException(); } - public void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, LibraryOptions options, bool refreshLibrary) + public void AddVirtualFolder(string name, string collectionType, LibraryOptions options, bool refreshLibrary) { if (string.IsNullOrWhiteSpace(name)) { @@ -2713,12 +2745,13 @@ namespace MediaBrowser.Server.Implementations.Library virtualFolderPath = Path.Combine(rootFolderPath, name); } - if (mediaPaths != null) + var mediaPathInfos = options.PathInfos; + if (mediaPathInfos != null) { - var invalidpath = mediaPaths.FirstOrDefault(i => !_fileSystem.DirectoryExists(i)); + var invalidpath = mediaPathInfos.FirstOrDefault(i => !_fileSystem.DirectoryExists(i.Path)); if (invalidpath != null) { - throw new ArgumentException("The specified path does not exist: " + invalidpath + "."); + throw new ArgumentException("The specified path does not exist: " + invalidpath.Path + "."); } } @@ -2740,11 +2773,11 @@ namespace MediaBrowser.Server.Implementations.Library CollectionFolder.SaveLibraryOptions(virtualFolderPath, options); - if (mediaPaths != null) + if (mediaPathInfos != null) { - foreach (var path in mediaPaths) + foreach (var path in mediaPathInfos) { - AddMediaPath(name, path); + AddMediaPathInternal(name, path, false); } } } @@ -2770,6 +2803,61 @@ namespace MediaBrowser.Server.Implementations.Library } } + private const string ShortcutFileExtension = ".mblink"; + private const string ShortcutFileSearch = "*" + ShortcutFileExtension; + public void AddMediaPath(string virtualFolderName, MediaPathInfo pathInfo) + { + AddMediaPathInternal(virtualFolderName, pathInfo, true); + } + + private void AddMediaPathInternal(string virtualFolderName, MediaPathInfo pathInfo, bool saveLibraryOptions) + { + if (pathInfo == null) + { + throw new ArgumentNullException("path"); + } + + var path = pathInfo.Path; + + if (string.IsNullOrWhiteSpace(path)) + { + throw new ArgumentNullException("path"); + } + + if (!_fileSystem.DirectoryExists(path)) + { + throw new DirectoryNotFoundException("The path does not exist."); + } + + var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; + var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); + + var shortcutFilename = _fileSystem.GetFileNameWithoutExtension(path); + + var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); + + while (_fileSystem.FileExists(lnk)) + { + shortcutFilename += "1"; + lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); + } + + _fileSystem.CreateShortcut(lnk, path); + + RemoveContentTypeOverrides(path); + + if (saveLibraryOptions) + { + var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); + + var list = libraryOptions.PathInfos.ToList(); + list.Add(pathInfo); + libraryOptions.PathInfos = list.ToArray(); + + CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions); + } + } + public void RemoveVirtualFolder(string name, bool refreshLibrary) { if (string.IsNullOrWhiteSpace(name)) @@ -2814,38 +2902,6 @@ namespace MediaBrowser.Server.Implementations.Library } } - private const string ShortcutFileExtension = ".mblink"; - private const string ShortcutFileSearch = "*" + ShortcutFileExtension; - public void AddMediaPath(string virtualFolderName, string path) - { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException("path"); - } - - if (!_fileSystem.DirectoryExists(path)) - { - throw new DirectoryNotFoundException("The path does not exist."); - } - - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); - - var shortcutFilename = _fileSystem.GetFileNameWithoutExtension(path); - - var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); - - while (_fileSystem.FileExists(lnk)) - { - shortcutFilename += "1"; - lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); - } - - _fileSystem.CreateShortcut(lnk, path); - - RemoveContentTypeOverrides(path); - } - private void RemoveContentTypeOverrides(string path) { if (string.IsNullOrWhiteSpace(path)) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index a3ca54b4ac..e358f9d25c 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -143,9 +143,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV continue; } + var mediaPathInfos = pathsToCreate.Select(i => new MediaPathInfo { Path = i }).ToArray(); + + var libraryOptions = new LibraryOptions + { + PathInfos = mediaPathInfos + }; try { - _libraryManager.AddVirtualFolder(recordingFolder.Name, recordingFolder.CollectionType, pathsToCreate.ToArray(), new LibraryOptions(), true); + _libraryManager.AddVirtualFolder(recordingFolder.Name, recordingFolder.CollectionType, libraryOptions, true); } catch (Exception ex) { -- cgit v1.2.3 From fdc2826709495c5313c4a61060fd420d0f8214b8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 24 Sep 2016 02:22:03 -0400 Subject: add network share config --- .../Library/LibraryStructureService.cs | 26 ++++++++++++++ MediaBrowser.Controller/Library/ILibraryManager.cs | 1 + .../IO/LibraryMonitor.cs | 5 ++- .../Library/LibraryManager.cs | 41 ++++++++++++++++++++-- .../LiveTv/LiveTvManager.cs | 6 +++- 5 files changed, 74 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Api/Library') diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index 0ed4ee2a2d..e872061a74 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -121,6 +121,18 @@ namespace MediaBrowser.Api.Library public bool RefreshLibrary { get; set; } } + [Route("/Library/VirtualFolders/Paths/Update", "POST")] + public class UpdateMediaPath : IReturnVoid + { + /// + /// Gets or sets the name. + /// + /// The name. + public string Name { get; set; } + + public MediaPathInfo PathInfo { get; set; } + } + [Route("/Library/VirtualFolders/Paths", "DELETE")] public class RemoveMediaPath : IReturnVoid { @@ -348,6 +360,20 @@ namespace MediaBrowser.Api.Library } } + /// + /// Posts the specified request. + /// + /// The request. + public void Post(UpdateMediaPath request) + { + if (string.IsNullOrWhiteSpace(request.Name)) + { + throw new ArgumentNullException("request"); + } + + _libraryManager.UpdateMediaPath(request.Name, request.PathInfo); + } + /// /// Deletes the specified request. /// diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 184a245c14..975c596594 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -559,6 +559,7 @@ namespace MediaBrowser.Controller.Library void AddVirtualFolder(string name, string collectionType, LibraryOptions options, bool refreshLibrary); void RemoveVirtualFolder(string name, bool refreshLibrary); void AddMediaPath(string virtualFolderName, MediaPathInfo path); + void UpdateMediaPath(string virtualFolderName, MediaPathInfo path); void RemoveMediaPath(string virtualFolderName, string path); QueryResult> GetGenres(InternalItemsQuery query); diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 6e0f9a3c48..bcc4e5dcfb 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -43,7 +43,10 @@ namespace MediaBrowser.Server.Implementations.IO // WMC temp recording directories that will constantly be written to "TempRec", - "TempSBE" + "TempSBE", + "@eaDir", + "eaDir", + "#recycle" }; private readonly IReadOnlyList _alwaysIgnoreSubstrings = new List diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index cef0022cfc..f62847bcc8 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -2858,6 +2858,32 @@ namespace MediaBrowser.Server.Implementations.Library } } + public void UpdateMediaPath(string virtualFolderName, MediaPathInfo pathInfo) + { + if (pathInfo == null) + { + throw new ArgumentNullException("path"); + } + + var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; + var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); + + var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); + + var list = libraryOptions.PathInfos.ToList(); + foreach (var originalPathInfo in list) + { + if (string.Equals(pathInfo.Path, originalPathInfo.Path, StringComparison.Ordinal)) + { + originalPathInfo.NetworkPath = pathInfo.NetworkPath; + break; + } + } + libraryOptions.PathInfos = list.ToArray(); + + CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions); + } + public void RemoveVirtualFolder(string name, bool refreshLibrary) { if (string.IsNullOrWhiteSpace(name)) @@ -2938,19 +2964,28 @@ namespace MediaBrowser.Server.Implementations.Library } var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - var path = Path.Combine(rootFolderPath, virtualFolderName); + var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); - if (!_fileSystem.DirectoryExists(path)) + if (!_fileSystem.DirectoryExists(virtualFolderPath)) { throw new DirectoryNotFoundException(string.Format("The media collection {0} does not exist", virtualFolderName)); } - var shortcut = Directory.EnumerateFiles(path, ShortcutFileSearch, SearchOption.AllDirectories).FirstOrDefault(f => _fileSystem.ResolveShortcut(f).Equals(mediaPath, StringComparison.OrdinalIgnoreCase)); + var shortcut = Directory.EnumerateFiles(virtualFolderPath, ShortcutFileSearch, SearchOption.AllDirectories).FirstOrDefault(f => _fileSystem.ResolveShortcut(f).Equals(mediaPath, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrEmpty(shortcut)) { _fileSystem.DeleteFile(shortcut); } + + var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); + + libraryOptions.PathInfos = libraryOptions + .PathInfos + .Where(i => !string.Equals(i.Path, mediaPath, StringComparison.Ordinal)) + .ToArray(); + + CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions); } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index dcef6e84a2..9b340a9f9e 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -699,7 +699,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv item.HomePageUrl = info.HomePageUrl; item.ProductionYear = info.ProductionYear; - item.PremiereDate = info.OriginalAirDate; + + if (!info.IsSeries || info.IsRepeat) + { + item.PremiereDate = info.OriginalAirDate; + } item.IndexNumber = info.EpisodeNumber; item.ParentIndexNumber = info.SeasonNumber; -- cgit v1.2.3 From b9cacd8076c00bfc371898c50315304927efaff8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 5 Oct 2016 03:15:29 -0400 Subject: update live streams --- MediaBrowser.Api/Library/ChapterService.cs | 30 --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 2 +- MediaBrowser.Api/MediaBrowser.Api.csproj | 1 - MediaBrowser.Api/Playback/BaseStreamingService.cs | 4 +- .../Progressive/BaseProgressiveStreamingService.cs | 35 ++-- .../Progressive/ProgressiveStreamWriter.cs | 29 ++- MediaBrowser.Api/Playback/StreamState.cs | 1 + .../Chapters/ChapterResponse.cs | 19 -- .../Chapters/ChapterSearchRequest.cs | 31 --- .../Chapters/IChapterManager.cs | 47 +---- .../Chapters/IChapterProvider.cs | 39 ---- .../Library/IMediaSourceManager.cs | 8 + .../Library/IMediaSourceProvider.cs | 3 +- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 3 +- MediaBrowser.Controller/LiveTv/ILiveTvService.cs | 6 + .../MediaBrowser.Controller.csproj | 3 - .../MediaBrowser.Model.Portable.csproj | 9 - .../MediaBrowser.Model.net35.csproj | 9 - MediaBrowser.Model/Chapters/ChapterProviderInfo.cs | 8 - MediaBrowser.Model/Chapters/RemoteChapterInfo.cs | 18 -- MediaBrowser.Model/Chapters/RemoteChapterResult.cs | 48 ----- MediaBrowser.Model/Configuration/ChapterOptions.cs | 16 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 3 - MediaBrowser.Providers/Chapters/ChapterManager.cs | 220 --------------------- .../MediaInfo/FFProbeVideoInfo.cs | 62 ------ .../MediaInfo/SubtitleScheduledTask.cs | 90 +++++++-- .../Channels/ChannelDynamicMediaSourceProvider.cs | 2 +- .../Library/LibraryManager.cs | 19 ++ .../Library/MediaSourceManager.cs | 19 +- .../LiveTv/EmbyTV/EmbyTV.cs | 11 +- .../LiveTv/LiveTvManager.cs | 28 ++- .../LiveTv/LiveTvMediaSourceProvider.cs | 11 +- .../TunerHosts/HdHomerun/HdHomerunLiveStream.cs | 79 +++++++- .../Sync/SyncedMediaSourceProvider.cs | 4 +- .../ApplicationHost.cs | 1 - 35 files changed, 293 insertions(+), 625 deletions(-) delete mode 100644 MediaBrowser.Api/Library/ChapterService.cs delete mode 100644 MediaBrowser.Controller/Chapters/ChapterResponse.cs delete mode 100644 MediaBrowser.Controller/Chapters/ChapterSearchRequest.cs delete mode 100644 MediaBrowser.Controller/Chapters/IChapterProvider.cs delete mode 100644 MediaBrowser.Model/Chapters/ChapterProviderInfo.cs delete mode 100644 MediaBrowser.Model/Chapters/RemoteChapterInfo.cs delete mode 100644 MediaBrowser.Model/Chapters/RemoteChapterResult.cs (limited to 'MediaBrowser.Api/Library') diff --git a/MediaBrowser.Api/Library/ChapterService.cs b/MediaBrowser.Api/Library/ChapterService.cs deleted file mode 100644 index 6b8dd18f10..0000000000 --- a/MediaBrowser.Api/Library/ChapterService.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediaBrowser.Controller.Chapters; -using MediaBrowser.Controller.Net; -using ServiceStack; -using System.Linq; - -namespace MediaBrowser.Api.Library -{ - [Route("/Providers/Chapters", "GET")] - public class GetChapterProviders : IReturnVoid - { - } - - [Authenticated] - public class ChapterService : BaseApiService - { - private readonly IChapterManager _chapterManager; - - public ChapterService(IChapterManager chapterManager) - { - _chapterManager = chapterManager; - } - - public object Get(GetChapterProviders request) - { - var result = _chapterManager.GetProviders().ToList(); - - return ToOptimizedResult(result); - } - } -} diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 4baae031f2..ed7a0990f1 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -705,7 +705,7 @@ namespace MediaBrowser.Api.LiveTv var outputHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); - outputHeaders["Content-Type"] = MimeTypes.GetMimeType(filePath); + outputHeaders["Content-Type"] = MediaBrowser.Model.Net.MimeTypes.GetMimeType(filePath); long startPosition = 0; diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 77949d1793..a986376503 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -79,7 +79,6 @@ - diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index bcf3bd28eb..0b2fad580a 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1888,7 +1888,9 @@ namespace MediaBrowser.Api.Playback } else { - mediaSource = await MediaSourceManager.GetLiveStream(request.LiveStreamId, cancellationToken).ConfigureAwait(false); + var liveStreamInfo = await MediaSourceManager.GetLiveStreamWithDirectStreamProvider(request.LiveStreamId, cancellationToken).ConfigureAwait(false); + mediaSource = liveStreamInfo.Item1; + state.DirectStreamProvider = liveStreamInfo.Item2; } var videoRequest = request as VideoStreamRequest; diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 4adf6fbca1..809eabef8f 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -121,32 +121,33 @@ namespace MediaBrowser.Api.Playback.Progressive var responseHeaders = new Dictionary(); - // Static remote stream - if (request.Static && state.InputProtocol == MediaProtocol.Http) + if (request.Static && state.DirectStreamProvider != null) { AddDlnaHeaders(state, responseHeaders, true); using (state) { - if (state.MediaPath.IndexOf("/livestreamfiles/", StringComparison.OrdinalIgnoreCase) != -1) - { - var parts = state.MediaPath.Split('/'); - var filename = parts[parts.Length - 2] + Path.GetExtension(parts[parts.Length - 1]); - var filePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, filename); + var outputHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); - var outputHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); + // TODO: Don't hardcode this + outputHeaders["Content-Type"] = MediaBrowser.Model.Net.MimeTypes.GetMimeType("file.ts"); - outputHeaders["Content-Type"] = MimeTypes.GetMimeType(filePath); + var streamSource = new ProgressiveFileCopier(state.DirectStreamProvider, outputHeaders, null, Logger, CancellationToken.None) + { + AllowEndOfFile = false + }; + return ResultFactory.GetAsyncStreamWriter(streamSource); + } + } - var streamSource = new ProgressiveFileCopier(FileSystem, filePath, outputHeaders, null, Logger, CancellationToken.None) - { - AllowEndOfFile = false - }; - return ResultFactory.GetAsyncStreamWriter(streamSource); - } + // Static remote stream + if (request.Static && state.InputProtocol == MediaProtocol.Http) + { + AddDlnaHeaders(state, responseHeaders, true); - return await GetStaticRemoteStreamResult(state, responseHeaders, isHeadRequest, cancellationTokenSource) - .ConfigureAwait(false); + using (state) + { + return await GetStaticRemoteStreamResult(state, responseHeaders, isHeadRequest, cancellationTokenSource).ConfigureAwait(false); } } diff --git a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs index f601f4aa30..3477ad57bd 100644 --- a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs +++ b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs @@ -7,6 +7,7 @@ using CommonIO; using MediaBrowser.Controller.Net; using System.Collections.Generic; using ServiceStack.Web; +using MediaBrowser.Controller.Library; namespace MediaBrowser.Api.Playback.Progressive { @@ -26,6 +27,8 @@ namespace MediaBrowser.Api.Playback.Progressive public long StartPosition { get; set; } public bool AllowEndOfFile = true; + private IDirectStreamProvider _directStreamProvider; + public ProgressiveFileCopier(IFileSystem fileSystem, string path, Dictionary outputHeaders, TranscodingJob job, ILogger logger, CancellationToken cancellationToken) { _fileSystem = fileSystem; @@ -36,6 +39,15 @@ namespace MediaBrowser.Api.Playback.Progressive _cancellationToken = cancellationToken; } + public ProgressiveFileCopier(IDirectStreamProvider directStreamProvider, Dictionary outputHeaders, TranscodingJob job, ILogger logger, CancellationToken cancellationToken) + { + _directStreamProvider = directStreamProvider; + _outputHeaders = outputHeaders; + _job = job; + _logger = logger; + _cancellationToken = cancellationToken; + } + public IDictionary Options { get @@ -44,22 +56,33 @@ namespace MediaBrowser.Api.Playback.Progressive } } + private Stream GetInputStream() + { + return _fileSystem.GetFileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true); + } + public async Task WriteToAsync(Stream outputStream) { try { + if (_directStreamProvider != null) + { + await _directStreamProvider.CopyToAsync(outputStream, _cancellationToken).ConfigureAwait(false); + return; + } + var eofCount = 0; - using (var fs = _fileSystem.GetFileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) + using (var inputStream = GetInputStream()) { if (StartPosition > 0) { - fs.Position = StartPosition; + inputStream.Position = StartPosition; } while (eofCount < 15 || !AllowEndOfFile) { - var bytesRead = await CopyToAsyncInternal(fs, outputStream, BufferSize, _cancellationToken).ConfigureAwait(false); + var bytesRead = await CopyToAsyncInternal(inputStream, outputStream, BufferSize, _cancellationToken).ConfigureAwait(false); //var position = fs.Position; //_logger.Debug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path); diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index 863bc01931..a59a7fe09e 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -37,6 +37,7 @@ namespace MediaBrowser.Api.Playback /// /// The log file stream. public Stream LogFileStream { get; set; } + public IDirectStreamProvider DirectStreamProvider { get; set; } public string InputContainer { get; set; } diff --git a/MediaBrowser.Controller/Chapters/ChapterResponse.cs b/MediaBrowser.Controller/Chapters/ChapterResponse.cs deleted file mode 100644 index 3c1b8ed079..0000000000 --- a/MediaBrowser.Controller/Chapters/ChapterResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediaBrowser.Model.Chapters; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Chapters -{ - public class ChapterResponse - { - /// - /// Gets or sets the chapters. - /// - /// The chapters. - public List Chapters { get; set; } - - public ChapterResponse() - { - Chapters = new List(); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Controller/Chapters/ChapterSearchRequest.cs b/MediaBrowser.Controller/Chapters/ChapterSearchRequest.cs deleted file mode 100644 index 982dc35bbc..0000000000 --- a/MediaBrowser.Controller/Chapters/ChapterSearchRequest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Chapters -{ - public class ChapterSearchRequest : IHasProviderIds - { - public string Language { get; set; } - - public VideoContentType ContentType { get; set; } - - public string MediaPath { get; set; } - public string SeriesName { get; set; } - public string Name { get; set; } - public int? IndexNumber { get; set; } - public int? IndexNumberEnd { get; set; } - public int? ParentIndexNumber { get; set; } - public int? ProductionYear { get; set; } - public long? RuntimeTicks { get; set; } - public Dictionary ProviderIds { get; set; } - - public bool SearchAllProviders { get; set; } - - public ChapterSearchRequest() - { - ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs index 27e06fb8dd..4b39e66cc2 100644 --- a/MediaBrowser.Controller/Chapters/IChapterManager.cs +++ b/MediaBrowser.Controller/Chapters/IChapterManager.cs @@ -1,6 +1,4 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Chapters; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Configuration; @@ -13,12 +11,6 @@ namespace MediaBrowser.Controller.Chapters /// public interface IChapterManager { - /// - /// Adds the parts. - /// - /// The chapter providers. - void AddParts(IEnumerable chapterProviders); - /// /// Gets the chapters. /// @@ -35,43 +27,6 @@ namespace MediaBrowser.Controller.Chapters /// Task. Task SaveChapters(string itemId, List chapters, CancellationToken cancellationToken); - /// - /// Searches the specified video. - /// - /// The video. - /// The cancellation token. - /// Task{IEnumerable{RemoteChapterResult}}. - Task> Search(Video video, CancellationToken cancellationToken); - - /// - /// Searches the specified request. - /// - /// The request. - /// The cancellation token. - /// Task{IEnumerable{RemoteChapterResult}}. - Task> Search(ChapterSearchRequest request, CancellationToken cancellationToken); - - /// - /// Gets the chapters. - /// - /// The identifier. - /// The cancellation token. - /// Task{ChapterResponse}. - Task GetChapters(string id, CancellationToken cancellationToken); - - /// - /// Gets the providers. - /// - /// The item identifier. - /// IEnumerable{ChapterProviderInfo}. - IEnumerable GetProviders(string itemId); - - /// - /// Gets the providers. - /// - /// IEnumerable{ChapterProviderInfo}. - IEnumerable GetProviders(); - /// /// Gets the configuration. /// diff --git a/MediaBrowser.Controller/Chapters/IChapterProvider.cs b/MediaBrowser.Controller/Chapters/IChapterProvider.cs deleted file mode 100644 index a7505347b8..0000000000 --- a/MediaBrowser.Controller/Chapters/IChapterProvider.cs +++ /dev/null @@ -1,39 +0,0 @@ -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Chapters; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Chapters -{ - public interface IChapterProvider - { - /// - /// Gets the name. - /// - /// The name. - string Name { get; } - - /// - /// Gets the supported media types. - /// - /// The supported media types. - IEnumerable SupportedMediaTypes { get; } - - /// - /// Searches the specified request. - /// - /// The request. - /// The cancellation token. - /// Task{IEnumerable{RemoteChapterResult}}. - Task> Search(ChapterSearchRequest request, CancellationToken cancellationToken); - - /// - /// Gets the chapters. - /// - /// The identifier. - /// The cancellation token. - /// Task{ChapterResponse}. - Task GetChapters(string id, CancellationToken cancellationToken); - } -} diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index c06470c5e0..1ab0e4cb06 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.IO; namespace MediaBrowser.Controller.Library { @@ -79,6 +80,8 @@ namespace MediaBrowser.Controller.Library /// The cancellation token. /// Task<MediaSourceInfo>. Task GetLiveStream(string id, CancellationToken cancellationToken); + + Task> GetLiveStreamWithDirectStreamProvider(string id, CancellationToken cancellationToken); /// /// Pings the media source. @@ -95,4 +98,9 @@ namespace MediaBrowser.Controller.Library /// Task. Task CloseLiveStream(string id); } + + public interface IDirectStreamProvider + { + Task CopyToAsync(Stream stream, CancellationToken cancellationToken); + } } diff --git a/MediaBrowser.Controller/Library/IMediaSourceProvider.cs b/MediaBrowser.Controller/Library/IMediaSourceProvider.cs index 56366e5a84..b0881ba7c4 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceProvider.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceProvider.cs @@ -3,6 +3,7 @@ using MediaBrowser.Model.Dto; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System; namespace MediaBrowser.Controller.Library { @@ -22,7 +23,7 @@ namespace MediaBrowser.Controller.Library /// The open token. /// The cancellation token. /// Task<MediaSourceInfo>. - Task OpenMediaSource(string openToken, CancellationToken cancellationToken); + Task> OpenMediaSource(string openToken, CancellationToken cancellationToken); /// /// Closes the media source. diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index d65d1ae300..a381c7980b 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Events; +using MediaBrowser.Controller.Library; namespace MediaBrowser.Controller.LiveTv { @@ -156,7 +157,7 @@ namespace MediaBrowser.Controller.LiveTv /// The media source identifier. /// The cancellation token. /// Task{StreamResponseInfo}. - Task GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken); + Task> GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken); /// /// Gets the program. diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs index d7d8336d02..94082b42ec 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Library; namespace MediaBrowser.Controller.LiveTv { @@ -245,4 +246,9 @@ namespace MediaBrowser.Controller.LiveTv /// Task. Task CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken); } + + public interface ISupportsDirectStreamProvider + { + Task> GetChannelStreamWithDirectStreamProvider(string channelId, string streamId, CancellationToken cancellationToken); + } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index d70fba742e..e9d2054da3 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -91,10 +91,7 @@ - - - diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index ad7dea0a5d..59e29087c9 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -160,15 +160,6 @@ Channels\ChannelQuery.cs - - Chapters\ChapterProviderInfo.cs - - - Chapters\RemoteChapterInfo.cs - - - Chapters\RemoteChapterResult.cs - Collections\CollectionCreationResult.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 61f2f3f13a..47ebb3a926 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -132,15 +132,6 @@ Channels\ChannelQuery.cs - - Chapters\ChapterProviderInfo.cs - - - Chapters\RemoteChapterInfo.cs - - - Chapters\RemoteChapterResult.cs - Collections\CollectionCreationResult.cs diff --git a/MediaBrowser.Model/Chapters/ChapterProviderInfo.cs b/MediaBrowser.Model/Chapters/ChapterProviderInfo.cs deleted file mode 100644 index 570407c573..0000000000 --- a/MediaBrowser.Model/Chapters/ChapterProviderInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace MediaBrowser.Model.Chapters -{ - public class ChapterProviderInfo - { - public string Name { get; set; } - public string Id { get; set; } - } -} \ No newline at end of file diff --git a/MediaBrowser.Model/Chapters/RemoteChapterInfo.cs b/MediaBrowser.Model/Chapters/RemoteChapterInfo.cs deleted file mode 100644 index f2674c8424..0000000000 --- a/MediaBrowser.Model/Chapters/RemoteChapterInfo.cs +++ /dev/null @@ -1,18 +0,0 @@ - -namespace MediaBrowser.Model.Chapters -{ - public class RemoteChapterInfo - { - /// - /// Gets or sets the start position ticks. - /// - /// The start position ticks. - public long StartPositionTicks { get; set; } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name { get; set; } - } -} diff --git a/MediaBrowser.Model/Chapters/RemoteChapterResult.cs b/MediaBrowser.Model/Chapters/RemoteChapterResult.cs deleted file mode 100644 index 425c3ded82..0000000000 --- a/MediaBrowser.Model/Chapters/RemoteChapterResult.cs +++ /dev/null @@ -1,48 +0,0 @@ - -namespace MediaBrowser.Model.Chapters -{ - public class RemoteChapterResult - { - /// - /// Gets or sets the identifier. - /// - /// The identifier. - public string Id { get; set; } - - /// - /// Gets or sets the run time ticks. - /// - /// The run time ticks. - public long? RunTimeTicks { get; set; } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name { get; set; } - - /// - /// Gets or sets the name of the provider. - /// - /// The name of the provider. - public string ProviderName { get; set; } - - /// - /// Gets or sets the community rating. - /// - /// The community rating. - public float? CommunityRating { get; set; } - - /// - /// Gets or sets the chapter count. - /// - /// The chapter count. - public int? ChapterCount { get; set; } - - /// - /// Gets or sets the name of the three letter iso language. - /// - /// The name of the three letter iso language. - public string ThreeLetterISOLanguageName { get; set; } - } -} diff --git a/MediaBrowser.Model/Configuration/ChapterOptions.cs b/MediaBrowser.Model/Configuration/ChapterOptions.cs index c7bb6f861e..1c2b0c5276 100644 --- a/MediaBrowser.Model/Configuration/ChapterOptions.cs +++ b/MediaBrowser.Model/Configuration/ChapterOptions.cs @@ -2,18 +2,10 @@ { public class ChapterOptions { - public bool DownloadMovieChapters { get; set; } - public bool DownloadEpisodeChapters { get; set; } + public bool EnableMovieChapterImageExtraction { get; set; } + public bool EnableEpisodeChapterImageExtraction { get; set; } + public bool EnableOtherVideoChapterImageExtraction { get; set; } - public string[] FetcherOrder { get; set; } - public string[] DisabledFetchers { get; set; } - - public ChapterOptions() - { - DownloadMovieChapters = true; - - DisabledFetchers = new string[] { }; - FetcherOrder = new string[] { }; - } + public bool ExtractDuringLibraryScan { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index c1a01680d8..69754204e5 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -84,9 +84,6 @@ - - - diff --git a/MediaBrowser.Providers/Chapters/ChapterManager.cs b/MediaBrowser.Providers/Chapters/ChapterManager.cs index 88811c850d..87aaafb39f 100644 --- a/MediaBrowser.Providers/Chapters/ChapterManager.cs +++ b/MediaBrowser.Providers/Chapters/ChapterManager.cs @@ -8,7 +8,6 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Chapters; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; @@ -22,7 +21,6 @@ namespace MediaBrowser.Providers.Chapters { public class ChapterManager : IChapterManager { - private IChapterProvider[] _providers; private readonly ILibraryManager _libraryManager; private readonly ILogger _logger; private readonly IServerConfigurationManager _config; @@ -36,224 +34,6 @@ namespace MediaBrowser.Providers.Chapters _itemRepo = itemRepo; } - public void AddParts(IEnumerable chapterProviders) - { - _providers = chapterProviders.ToArray(); - } - - public Task> Search(Video video, CancellationToken cancellationToken) - { - VideoContentType mediaType; - - if (video is Episode) - { - mediaType = VideoContentType.Episode; - } - else if (video is Movie) - { - mediaType = VideoContentType.Movie; - } - else - { - // These are the only supported types - return Task.FromResult>(new List()); - } - - var request = new ChapterSearchRequest - { - ContentType = mediaType, - IndexNumber = video.IndexNumber, - Language = video.GetPreferredMetadataLanguage(), - MediaPath = video.Path, - Name = video.Name, - ParentIndexNumber = video.ParentIndexNumber, - ProductionYear = video.ProductionYear, - ProviderIds = video.ProviderIds, - RuntimeTicks = video.RunTimeTicks, - SearchAllProviders = false - }; - - var episode = video as Episode; - - if (episode != null) - { - request.IndexNumberEnd = episode.IndexNumberEnd; - request.SeriesName = episode.SeriesName; - } - - return Search(request, cancellationToken); - } - - public async Task> Search(ChapterSearchRequest request, CancellationToken cancellationToken) - { - var contentType = request.ContentType; - var providers = GetInternalProviders(false) - .Where(i => i.SupportedMediaTypes.Contains(contentType)) - .ToList(); - - // If not searching all, search one at a time until something is found - if (!request.SearchAllProviders) - { - foreach (var provider in providers) - { - try - { - var currentResults = await Search(request, provider, cancellationToken).ConfigureAwait(false); - - if (currentResults.Count > 0) - { - return currentResults; - } - } - catch (Exception ex) - { - _logger.ErrorException("Error downloading subtitles from {0}", ex, provider.Name); - } - } - return new List(); - } - - var tasks = providers.Select(async i => - { - try - { - return await Search(request, i, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error downloading subtitles from {0}", ex, i.Name); - return new List(); - } - }); - - var results = await Task.WhenAll(tasks).ConfigureAwait(false); - - return results.SelectMany(i => i); - } - - private async Task> Search(ChapterSearchRequest request, - IChapterProvider provider, - CancellationToken cancellationToken) - { - var searchResults = await provider.Search(request, cancellationToken).ConfigureAwait(false); - - var list = searchResults.ToList(); - - foreach (var result in list) - { - result.Id = GetProviderId(provider.Name) + "_" + result.Id; - result.ProviderName = provider.Name; - } - - return list; - } - - public Task GetChapters(string id, CancellationToken cancellationToken) - { - var parts = id.Split(new[] { '_' }, 2); - - var provider = GetProvider(parts.First()); - id = parts.Last(); - - return provider.GetChapters(id, cancellationToken); - } - - public IEnumerable GetProviders(string itemId) - { - var video = _libraryManager.GetItemById(itemId) as Video; - VideoContentType mediaType; - - if (video is Episode) - { - mediaType = VideoContentType.Episode; - } - else if (video is Movie) - { - mediaType = VideoContentType.Movie; - } - else - { - // These are the only supported types - return new List(); - } - - var providers = GetInternalProviders(false) - .Where(i => i.SupportedMediaTypes.Contains(mediaType)); - - return GetInfos(providers); - } - - public IEnumerable GetProviders() - { - return GetInfos(GetInternalProviders(true)); - } - - private IEnumerable GetInternalProviders(bool includeDisabledProviders) - { - var providers = _providers; - - if (!includeDisabledProviders) - { - var options = GetConfiguration(); - - providers = providers - .Where(i => !options.DisabledFetchers.Contains(i.Name)) - .ToArray(); - } - - return providers - .OrderBy(GetConfiguredOrder) - .ThenBy(GetDefaultOrder) - .ToArray(); - } - - private IEnumerable GetInfos(IEnumerable providers) - { - return providers.Select(i => new ChapterProviderInfo - { - Name = i.Name, - Id = GetProviderId(i.Name) - }); - } - - private string GetProviderId(string name) - { - return name.ToLower().GetMD5().ToString("N"); - } - - private IChapterProvider GetProvider(string id) - { - return _providers.First(i => string.Equals(id, GetProviderId(i.Name))); - } - - private int GetConfiguredOrder(IChapterProvider provider) - { - var options = GetConfiguration(); - - // See if there's a user-defined order - var index = Array.IndexOf(options.FetcherOrder, provider.Name); - - if (index != -1) - { - return index; - } - - // Not configured. Just return some high number to put it at the end. - return 100; - } - - private int GetDefaultOrder(IChapterProvider provider) - { - var hasOrder = provider as IHasOrder; - - if (hasOrder != null) - { - return hasOrder.Order; - } - - return 0; - } - public IEnumerable GetChapters(string itemId) { return _itemRepo.GetChapters(new Guid(itemId)); diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 66fe7ea81f..8c87e991e7 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -238,22 +238,6 @@ namespace MediaBrowser.Providers.MediaInfo if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || options.MetadataRefreshMode == MetadataRefreshMode.Default) { - var chapterOptions = _chapterManager.GetConfiguration(); - - try - { - var remoteChapters = await DownloadChapters(video, chapters, chapterOptions, cancellationToken).ConfigureAwait(false); - - if (remoteChapters.Count > 0) - { - chapters = remoteChapters; - } - } - catch (Exception ex) - { - _logger.ErrorException("Error downloading chapters", ex); - } - if (chapters.Count == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video)) { AddDummyChapters(video, chapters); @@ -561,52 +545,6 @@ namespace MediaBrowser.Providers.MediaInfo currentStreams.AddRange(externalSubtitleStreams); } - private async Task> DownloadChapters(Video video, List currentChapters, ChapterOptions options, CancellationToken cancellationToken) - { - if ((options.DownloadEpisodeChapters && - video is Episode) || - (options.DownloadMovieChapters && - video is Movie)) - { - var results = await _chapterManager.Search(video, cancellationToken).ConfigureAwait(false); - - var result = results.FirstOrDefault(); - - if (result != null) - { - var chapters = await _chapterManager.GetChapters(result.Id, cancellationToken).ConfigureAwait(false); - - var chapterInfos = chapters.Chapters.Select(i => new ChapterInfo - { - Name = i.Name, - StartPositionTicks = i.StartPositionTicks - - }).ToList(); - - if (chapterInfos.All(i => i.StartPositionTicks == 0)) - { - if (currentChapters.Count >= chapterInfos.Count) - { - var index = 0; - foreach (var info in chapterInfos) - { - info.StartPositionTicks = currentChapters[index].StartPositionTicks; - index++; - } - } - else - { - chapterInfos.Clear(); - } - } - - return chapterInfos; - } - } - - return new List(); - } - /// /// The dummy chapter duration /// diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index 79da291b77..2490f71453 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -14,6 +14,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using System.IO; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.MediaInfo { @@ -24,14 +26,16 @@ namespace MediaBrowser.Providers.MediaInfo private readonly ISubtitleManager _subtitleManager; private readonly IMediaSourceManager _mediaSourceManager; private readonly ILogger _logger; + private IJsonSerializer _json; - public SubtitleScheduledTask(ILibraryManager libraryManager, IServerConfigurationManager config, ISubtitleManager subtitleManager, ILogger logger, IMediaSourceManager mediaSourceManager) + public SubtitleScheduledTask(ILibraryManager libraryManager, IJsonSerializer json, IServerConfigurationManager config, ISubtitleManager subtitleManager, ILogger logger, IMediaSourceManager mediaSourceManager) { _libraryManager = libraryManager; _config = config; _subtitleManager = subtitleManager; _logger = logger; _mediaSourceManager = mediaSourceManager; + _json = json; } public string Name @@ -58,38 +62,65 @@ namespace MediaBrowser.Providers.MediaInfo { var options = GetOptions(); - var videos = _libraryManager.RootFolder - .GetRecursiveChildren(i => - { - if (!(i is Video)) - { - return false; - } + var types = new List(); - if (i.LocationType == LocationType.Remote || i.LocationType == LocationType.Virtual) - { - return false; - } + if (options.DownloadEpisodeSubtitles) + { + types.Add("Episode"); + } + if (options.DownloadMovieSubtitles) + { + types.Add("Movie"); + } - return (options.DownloadEpisodeSubtitles && - i is Episode) || - (options.DownloadMovieSubtitles && - i is Movie); - }) - .Cast