diff --git a/MediaBrowser.Api/LiveTv/LiveTvImageService.cs b/MediaBrowser.Api/LiveTv/LiveTvImageService.cs deleted file mode 100644 index 65c4e5e23a..0000000000 --- a/MediaBrowser.Api/LiveTv/LiveTvImageService.cs +++ /dev/null @@ -1,195 +0,0 @@ -using MediaBrowser.Api.Images; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using ServiceStack; -using ServiceStack.Text.Controller; -using ServiceStack.Web; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Api.LiveTv -{ - [Route("/LiveTv/Channels/{Id}/Images/{Type}", "POST")] - [Route("/LiveTv/Channels/{Id}/Images/{Type}/{Index}", "POST")] - [Api(Description = "Posts an item image")] - public class PostChannelImage : DeleteImageRequest, IRequiresRequestStream, IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - /// - /// The raw Http Request Input Stream - /// - /// The request stream. - public Stream RequestStream { get; set; } - } - - [Route("/LiveTv/Channels/{Id}/Images/{Type}", "DELETE")] - [Route("/LiveTv/Channels/{Id}/Images/{Type}/{Index}", "DELETE")] - [Api(Description = "Deletes an item image")] - public class DeleteChannelImage : DeleteImageRequest, IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public string Id { get; set; } - } - [Route("/LiveTv/Channels/{Id}/Images/{Type}", "GET")] - [Route("/LiveTv/Channels/{Id}/Images/{Type}/{Index}", "GET")] - [Api(Description = "Gets an item image")] - public class GetChannelImage : ImageRequest - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - [Route("/LiveTv/Recordings/{Id}/Images/{Type}", "GET")] - [Route("/LiveTv/Recordings/{Id}/Images/{Type}/{Index}", "GET")] - [Api(Description = "Gets an item image")] - public class GetRecordingImage : ImageRequest - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - [Route("/LiveTv/Programs/{Id}/Images/{Type}", "GET")] - [Route("/LiveTv/Programs/{Id}/Images/{Type}/{Index}", "GET")] - [Api(Description = "Gets an item image")] - public class GetProgramImage : ImageRequest - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Program Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - [Route("/LiveTv/Channels/{Id}/Images", "GET")] - [Api(Description = "Gets information about an item's images")] - public class GetChannelImageInfos : IReturn> - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - public class LiveTvImageService : BaseApiService - { - private readonly ILiveTvManager _liveTv; - - private readonly IUserManager _userManager; - - private readonly ILibraryManager _libraryManager; - - private readonly IApplicationPaths _appPaths; - - private readonly IProviderManager _providerManager; - - private readonly IItemRepository _itemRepo; - private readonly IDtoService _dtoService; - private readonly IImageProcessor _imageProcessor; - - public LiveTvImageService(ILiveTvManager liveTv, IUserManager userManager, ILibraryManager libraryManager, IApplicationPaths appPaths, IProviderManager providerManager, IItemRepository itemRepo, IDtoService dtoService, IImageProcessor imageProcessor) - { - _liveTv = liveTv; - _userManager = userManager; - _libraryManager = libraryManager; - _appPaths = appPaths; - _providerManager = providerManager; - _itemRepo = itemRepo; - _dtoService = dtoService; - _imageProcessor = imageProcessor; - } - - public object Get(GetChannelImageInfos request) - { - var item = _liveTv.GetInternalChannel(request.Id); - - var result = GetImageService().GetItemImageInfos(item); - - return ToOptimizedResult(result); - } - - public object Get(GetChannelImage request) - { - var item = _liveTv.GetInternalChannel(request.Id); - - return GetImageService().GetImage(request, item); - } - - public object Get(GetRecordingImage request) - { - var item = _liveTv.GetInternalRecording(request.Id, CancellationToken.None).Result; - - return GetImageService().GetImage(request, item); - } - - public object Get(GetProgramImage request) - { - var item = _liveTv.GetInternalProgram(request.Id); - - return GetImageService().GetImage(request, item); - } - - public void Post(PostChannelImage request) - { - var pathInfo = PathInfo.Parse(Request.PathInfo); - var id = pathInfo.GetArgumentValue(2); - - request.Type = (ImageType)Enum.Parse(typeof(ImageType), pathInfo.GetArgumentValue(4), true); - - var item = _liveTv.GetInternalChannel(id); - - var task = GetImageService().PostImage(item, request.RequestStream, request.Type, Request.ContentType); - - Task.WaitAll(task); - } - - public void Delete(DeleteChannelImage request) - { - var item = _liveTv.GetInternalChannel(request.Id); - - var task = item.DeleteImage(request.Type, request.Index); - - Task.WaitAll(task); - } - - private ImageService GetImageService() - { - return new ImageService(_userManager, _libraryManager, _appPaths, _providerManager, _itemRepo, _dtoService, - _imageProcessor) - { - ResultFactory = ResultFactory, - Request = Request - }; - } - } -} diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 4fc989fc50..409d152f79 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -90,7 +90,6 @@ - diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 440632825e..0ae96effde 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -163,6 +163,11 @@ namespace MediaBrowser.Api.Playback.Progressive { responseHeaders["ContentFeatures.DLNA.ORG"] = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); } + + foreach (var item in responseHeaders) + { + Request.Response.AddHeader(item.Key, item.Value); + } } /// diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 036ac7e81e..c3a87fc317 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -327,5 +327,11 @@ namespace MediaBrowser.Controller.Library /// The paths. /// IEnumerable{System.String}. IEnumerable NormalizeRootPathList(IEnumerable paths); + + /// + /// Registers the item. + /// + /// The item. + void RegisterItem(BaseItem item); } } \ No newline at end of file diff --git a/MediaBrowser.Mono.userprefs b/MediaBrowser.Mono.userprefs index da74b9ccd0..a65710851f 100644 --- a/MediaBrowser.Mono.userprefs +++ b/MediaBrowser.Mono.userprefs @@ -4,7 +4,7 @@ - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 6b87f1dfed..e686e7eda0 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -45,6 +45,12 @@ v4.5 + + ..\packages\MediaBrowser.BdInfo.1.0.0.7\lib\net35\BDInfo.dll + + + ..\packages\MediaBrowser.BdInfo.1.0.0.7\lib\net35\DvdLib.dll + diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs index 8e07bc2667..e386c78a4a 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.MediaInfo; +using DvdLib.Ifo; +using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Localization; @@ -132,12 +133,30 @@ namespace MediaBrowser.Providers.MediaInfo if (item.VideoType == VideoType.Dvd || (item.IsoType.HasValue && item.IsoType == IsoType.Dvd)) { - PopulateDvdStreamFiles(item, mount); + FetchFromDvdLib(item, mount); } base.OnPreFetch(item, mount); } + private void FetchFromDvdLib(Video item, IIsoMount mount) + { + var path = mount == null ? item.Path : mount.MountedPath; + var dvd = new Dvd(path); + + item.RunTimeTicks = dvd.Titles.Select(GetRuntime).Max(); + + PopulateDvdStreamFiles(item, mount); + } + + private long GetRuntime(Title title) + { + return title.ProgramChains + .Select(i => (TimeSpan)i.PlaybackTime) + .Select(i => i.Ticks) + .Sum(); + } + public override async Task FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) { var video = (Video)item; diff --git a/MediaBrowser.Providers/packages.config b/MediaBrowser.Providers/packages.config index f40bfae21f..4a4fef846f 100644 --- a/MediaBrowser.Providers/packages.config +++ b/MediaBrowser.Providers/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs index 798632af7a..2419320a54 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -360,11 +360,19 @@ namespace MediaBrowser.Server.Implementations.HttpServer var compress = ShouldCompressResponse(requestContext, contentType); - var hasOptions = GetStaticResult(requestContext, responseHeaders, contentType, factoryFn, compress, isHeadRequest).Result; + var hasOptions = GetStaticResult(requestContext, responseHeaders, contentType, factoryFn, compress, isHeadRequest); - AddResponseHeaders(hasOptions, responseHeaders); + return GetStaticResultTask(hasOptions, responseHeaders); + } + + private async Task GetStaticResultTask(Task optionsTask, + IEnumerable> responseHeaders) + { + var options = await optionsTask.ConfigureAwait(false); + + AddResponseHeaders(options, responseHeaders); - return hasOptions; + return options; } /// diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 8e4e71fd42..fc5497fa39 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -407,6 +407,11 @@ namespace MediaBrowser.Server.Implementations.Library } } + RegisterItem(item); + } + + public void RegisterItem(BaseItem item) + { LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; }); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index b6622a3100..182ce1cbc7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -30,21 +30,23 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly ILogger _logger; private readonly IItemRepository _itemRepo; private readonly IUserManager _userManager; + private readonly ILibraryManager _libraryManager; private readonly LiveTvDtoService _tvDtoService; private readonly List _services = new List(); - private Dictionary _channels = new Dictionary(); + private List _channelIdList = new List(); private Dictionary _programs = new Dictionary(); - public LiveTvManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager) + public LiveTvManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager) { _appPaths = appPaths; _fileSystem = fileSystem; _logger = logger; _itemRepo = itemRepo; _userManager = userManager; + _libraryManager = libraryManager; _tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger, _itemRepo); } @@ -75,7 +77,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId)); - IEnumerable channels = _channels.Values; + var channels = _channelIdList.Select(_libraryManager.GetItemById) + .Where(i => i != null) + .OfType(); if (user != null) { @@ -144,10 +148,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv private LiveTvChannel GetInternalChannel(Guid id) { - LiveTvChannel channel = null; - - _channels.TryGetValue(id, out channel); - return channel; + return _libraryManager.GetItemById(id) as LiveTvChannel; } public LiveTvProgram GetInternalProgram(string id) @@ -320,6 +321,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv await item.RefreshMetadata(cancellationToken, forceSave: isNew, resetResolveArgs: false); + _libraryManager.RegisterItem((BaseItem)item); + return item; } @@ -477,6 +480,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv var item = await GetChannel(channelInfo.Item2, channelInfo.Item1, cancellationToken).ConfigureAwait(false); list.Add(item); + + _libraryManager.RegisterItem(item); } catch (OperationCanceledException) { @@ -493,7 +498,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv progress.Report(5 * percent + 10); } - _channels = list.ToDictionary(i => i.Id); + + _channelIdList = list.Select(i => i.Id).ToList(); progress.Report(15); numComplete = 0; diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index b083b7b847..6513446b7e 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -48,6 +48,13 @@ ..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll + + False + ..\packages\MediaBrowser.BdInfo.1.0.0.7\lib\net35\BDInfo.dll + + + ..\packages\MediaBrowser.BdInfo.1.0.0.7\lib\net35\DvdLib.dll + ..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll @@ -68,9 +75,6 @@ ..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll - - ..\packages\MediaBrowser.BdInfo.1.0.0.5\lib\net20\BDInfo.dll - False ..\ThirdParty\System.Data.SQLite.ManagedOnly\x86\1.0.90.0\net40\System.Data.SQLite.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index a504bc6ab5..503e916e5e 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,7 +1,7 @@  - + \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index bf20c8fb87..a14ffc4332 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -285,7 +285,7 @@ namespace MediaBrowser.ServerApplication DtoService = new DtoService(Logger, LibraryManager, UserManager, UserDataManager, ItemRepository, ImageProcessor); RegisterSingleInstance(DtoService); - LiveTvManager = new LiveTvManager(ApplicationPaths, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager); + LiveTvManager = new LiveTvManager(ApplicationPaths, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager); RegisterSingleInstance(LiveTvManager); progress.Report(15); diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js index cbe815c03a..fe0e5e541f 100644 --- a/MediaBrowser.WebDashboard/ApiClient.js +++ b/MediaBrowser.WebDashboard/ApiClient.js @@ -1594,9 +1594,6 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi if (itemType == "Artist") { url = self.getUrl("Artists/" + self.encodeName(itemName) + "/Images"); } - else if (itemType == "Channel") { - url = self.getUrl("LiveTv/Channels/" + itemId + "/Images"); - } else if (itemType == "Genre") { url = self.getUrl("Genres/" + self.encodeName(itemName) + "/Images"); } else if (itemType == "GameGenre") { @@ -1667,9 +1664,6 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi if (itemType == "Artist") { url = self.getUrl("Artists/" + self.encodeName(itemName) + "/Images/" + imageType + "/" + imageIndex + "/Index", options); } - else if (itemType == "Channel") { - url = self.getUrl("LiveTv/Channels/" + itemId + "/Images/" + imageType + "/" + imageIndex + "/Index", options); - } else if (itemType == "Genre") { url = self.getUrl("Genres/" + self.encodeName(itemName) + "/Images/" + imageType + "/" + imageIndex + "/Index", options); } else if (itemType == "GameGenre") { @@ -1701,9 +1695,6 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi if (itemType == "Artist") { url = self.getUrl("Artists/" + self.encodeName(itemName) + "/Images"); } - else if (itemType == "Channel") { - url = self.getUrl("LiveTv/Channels/" + itemId + "/Images"); - } else if (itemType == "Genre") { url = self.getUrl("Genres/" + self.encodeName(itemName) + "/Images"); } else if (itemType == "GameGenre") { @@ -1838,9 +1829,6 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi if (itemType == "Artist") { url = self.getUrl("Artists/" + self.encodeName(itemName) + "/Images"); } - else if (itemType == "Channel") { - url = self.getUrl("LiveTv/Channels/" + itemId + "/Images"); - } else if (itemType == "Genre") { url = self.getUrl("Genres/" + self.encodeName(itemName) + "/Images"); } else if (itemType == "GameGenre") { diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index c47d67815e..6c512e8bb6 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file