From daaae69df575f1d7692ba29d6f5ddd4c59516f82 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 9 Oct 2016 03:18:43 -0400 Subject: [PATCH] add playback of in-progress recordings --- MediaBrowser.Api/Library/LibraryService.cs | 32 +---- MediaBrowser.Api/LiveTv/LiveTvService.cs | 29 +++- .../Channels/IChannelManager.cs | 10 -- .../Entities/AggregateFolder.cs | 6 + .../Entities/Audio/Audio.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 28 ++-- MediaBrowser.Controller/Entities/Folder.cs | 41 +++--- MediaBrowser.Controller/Entities/Game.cs | 11 +- .../Entities/IHasThemeMedia.cs | 23 ---- .../Entities/InternalItemsQuery.cs | 1 + .../Entities/Movies/Movie.cs | 7 +- MediaBrowser.Controller/Entities/TV/Season.cs | 2 - MediaBrowser.Controller/Entities/UserView.cs | 1 - .../Entities/UserViewBuilder.cs | 16 +-- MediaBrowser.Controller/Entities/Video.cs | 8 +- .../LiveTv/ILiveTvManager.cs | 10 +- .../LiveTv/ILiveTvRecording.cs | 1 + .../LiveTv/LiveTvAudioRecording.cs | 3 +- .../LiveTv/LiveTvVideoRecording.cs | 3 +- .../MediaBrowser.Controller.csproj | 1 - .../Providers/BaseItemXmlParser.cs | 4 +- .../ContentDirectory/ControlHandler.cs | 61 +-------- MediaBrowser.Dlna/Main/DlnaEntryPoint.cs | 2 +- .../Savers/PersonXmlSaver.cs | 4 +- .../Configuration/DlnaOptions.cs | 1 - MediaBrowser.Model/Dto/BaseItemDto.cs | 1 - MediaBrowser.Model/LiveTv/RecordingStatus.cs | 1 - .../LiveTv/SeriesTimerInfoDto.cs | 24 ++++ MediaBrowser.Model/Querying/ItemFields.cs | 2 - .../Manager/ProviderUtils.cs | 8 ++ .../Movies/GenericMovieDbInfo.cs | 12 +- .../People/MovieDbPersonProvider.cs | 6 +- .../People/PersonMetadataService.cs | 8 -- .../Channels/ChannelManager.cs | 92 ------------- .../Dto/DtoService.cs | 14 +- .../SocketSharp/WebSocketSharpRequest.cs | 2 +- .../Library/LibraryManager.cs | 13 +- .../Resolvers/Audio/MusicAlbumResolver.cs | 2 +- .../Resolvers/Audio/MusicArtistResolver.cs | 13 +- .../Library/Resolvers/FolderResolver.cs | 1 - .../Library/Resolvers/TV/SeriesResolver.cs | 34 +++-- .../LiveTv/EmbyTV/EmbyTV.cs | 104 +++++++++++++-- .../LiveTv/LiveTvDtoService.cs | 29 ++++ .../LiveTv/LiveTvManager.cs | 43 +++--- .../LiveTv/LiveTvMediaSourceProvider.cs | 4 +- .../Persistence/SqliteItemRepository.cs | 124 +++++++++++++++++- .../ApplicationHost.cs | 106 +++++++++++++++ .../Parsers/BaseNfoParser.cs | 7 +- .../Savers/BaseNfoSaver.cs | 10 +- 49 files changed, 570 insertions(+), 397 deletions(-) delete mode 100644 MediaBrowser.Controller/Entities/IHasThemeMedia.cs diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index c6b637f015..e0dfcb9ad2 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -835,14 +835,14 @@ namespace MediaBrowser.Api.Library : (Folder)_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); - while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null) + while (item.ThemeSongIds.Count == 0 && request.InheritFromParent && item.GetParent() != null) { item = item.GetParent(); } var dtoOptions = GetDtoOptions(request); - var dtos = GetThemeSongIds(item).Select(_libraryManager.GetItemById) + var dtos = item.ThemeSongIds.Select(_libraryManager.GetItemById) .Where(i => i != null) .OrderBy(i => i.SortName) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)); @@ -879,14 +879,14 @@ namespace MediaBrowser.Api.Library : (Folder)_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); - while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null) + while (item.ThemeVideoIds.Count == 0 && request.InheritFromParent && item.GetParent() != null) { item = item.GetParent(); } var dtoOptions = GetDtoOptions(request); - var dtos = GetThemeVideoIds(item).Select(_libraryManager.GetItemById) + var dtos = item.ThemeVideoIds.Select(_libraryManager.GetItemById) .Where(i => i != null) .OrderBy(i => i.SortName) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)); @@ -901,30 +901,6 @@ namespace MediaBrowser.Api.Library }; } - private List GetThemeVideoIds(BaseItem item) - { - var i = item as IHasThemeMedia; - - if (i != null) - { - return i.ThemeVideoIds; - } - - return new List(); - } - - private List GetThemeSongIds(BaseItem item) - { - var i = item as IHasThemeMedia; - - if (i != null) - { - return i.ThemeSongIds; - } - - return new List(); - } - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); public object Get(GetYearIndex request) diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index ebfced0f41..4217cd6abe 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -677,6 +677,12 @@ namespace MediaBrowser.Api.LiveTv public string Container { get; set; } } + [Route("/LiveTv/LiveRecordings/{Id}/stream", "GET", Summary = "Gets a live tv channel")] + public class GetLiveRecordingFile + { + public string Id { get; set; } + } + public class LiveTvService : BaseApiService { private readonly ILiveTvManager _liveTvManager; @@ -698,13 +704,32 @@ namespace MediaBrowser.Api.LiveTv _fileSystem = fileSystem; } + public async Task Get(GetLiveRecordingFile request) + { + var path = EmbyTV.Current.GetActiveRecordingPath(request.Id); + + if (path == null) + { + throw new FileNotFoundException(); + } + + var outputHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); + + outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType(path); + + var streamSource = new ProgressiveFileCopier(_fileSystem, path, outputHeaders, null, Logger, CancellationToken.None) + { + AllowEndOfFile = false + }; + return ResultFactory.GetAsyncStreamWriter(streamSource); + } + public async Task Get(GetLiveStreamFile request) { var directStreamProvider = (await EmbyTV.Current.GetLiveStream(request.Id).ConfigureAwait(false)) as IDirectStreamProvider; var outputHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); - // TODO: Don't hardcode this - outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType("file.ts"); + outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType("file." + request.Container); var streamSource = new ProgressiveFileCopier(directStreamProvider, outputHeaders, null, Logger, CancellationToken.None) { diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs index 3c46247a72..9177e2d813 100644 --- a/MediaBrowser.Controller/Channels/IChannelManager.cs +++ b/MediaBrowser.Controller/Channels/IChannelManager.cs @@ -134,15 +134,5 @@ namespace MediaBrowser.Controller.Channels /// The cancellation token. /// BaseItemDto. Task GetChannelFolder(string userId, CancellationToken cancellationToken); - - /// - /// Downloads the channel item. - /// - /// The item. - /// The destination path. - /// The progress. - /// The cancellation token. - /// Task. - Task DownloadChannelItem(BaseItem item, string destinationPath, IProgress progress, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index efc4502481..9709813dcd 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -34,6 +34,12 @@ namespace MediaBrowser.Controller.Entities } } + [IgnoreDataMember] + public override bool IsPhysicalRoot + { + get { return true; } + } + public override bool CanDelete() { return false; diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 00657370e1..891fb7d522 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -62,7 +62,7 @@ namespace MediaBrowser.Controller.Entities.Audio [IgnoreDataMember] public override bool SupportsAddingToPlaylist { - get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; } + get { return true; } } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index eb84765fba..cc4a8fdb9c 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -37,6 +37,8 @@ namespace MediaBrowser.Controller.Entities { protected BaseItem() { + ThemeSongIds = new List(); + ThemeVideoIds = new List(); Keywords = new List(); Tags = new List(); Genres = new List(); @@ -45,6 +47,7 @@ namespace MediaBrowser.Controller.Entities LockedFields = new List(); ImageInfos = new List(); InheritedTags = new List(); + ProductionLocations = new List(); } public static readonly char[] SlugReplaceChars = { '?', '/', '&' }; @@ -65,6 +68,9 @@ namespace MediaBrowser.Controller.Entities public static string ThemeSongFilename = "theme"; public static string ThemeVideosFolderName = "backdrops"; + public List ThemeSongIds { get; set; } + public List ThemeVideoIds { get; set; } + [IgnoreDataMember] public string PreferredMetadataCountryCode { get; set; } [IgnoreDataMember] @@ -876,6 +882,7 @@ namespace MediaBrowser.Controller.Entities public List Tags { get; set; } public List Keywords { get; set; } + public List ProductionLocations { get; set; } /// /// Gets or sets the home page URL. @@ -991,7 +998,7 @@ namespace MediaBrowser.Controller.Entities /// Loads the theme songs. /// /// List{Audio.Audio}. - private IEnumerable LoadThemeSongs(List fileSystemChildren, IDirectoryService directoryService) + private static IEnumerable LoadThemeSongs(List fileSystemChildren, IDirectoryService directoryService) { var files = fileSystemChildren.Where(i => i.IsDirectory) .Where(i => string.Equals(i.Name, ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) @@ -1027,7 +1034,7 @@ namespace MediaBrowser.Controller.Entities /// Loads the video backdrops. /// /// List{Video}. - private IEnumerable