From b3595eab6a94fda4f81f637007b2ac79e8a85065 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 8 Oct 2016 14:51:07 -0400 Subject: [PATCH 1/2] update music brainz to fetch overview --- .../Configuration/ServerConfiguration.cs | 6 +- MediaBrowser.Model/Dto/BaseItemDto.cs | 2 + .../Providers/RemoteSearchResult.cs | 3 +- .../Music/MusicBrainzAlbumProvider.cs | 60 +++++++++++++++---- .../Music/MusicBrainzArtistProvider.cs | 11 +++- .../Dto/DtoService.cs | 6 ++ .../Persistence/SqliteItemRepository.cs | 10 +++- 7 files changed, 78 insertions(+), 20 deletions(-) diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 2cdd88775f..a1e5637a49 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -435,7 +435,8 @@ namespace MediaBrowser.Model.Configuration Limit = 0, Type = ImageType.Disc } - } + }, + DisabledMetadataFetchers = new []{ "TheAudioDB" } }, new MetadataOptions(1, 1280) @@ -473,7 +474,8 @@ namespace MediaBrowser.Model.Configuration Limit = 0, Type = ImageType.Logo } - } + }, + DisabledMetadataFetchers = new []{ "TheAudioDB" } }, new MetadataOptions(1, 1280) diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 7d21f9861e..598f8c58b4 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -169,6 +169,8 @@ namespace MediaBrowser.Model.Dto /// The game system. public string GameSystem { get; set; } + public string[] ProductionLocations { get; set; } + /// /// Gets or sets the critic rating summary. /// diff --git a/MediaBrowser.Model/Providers/RemoteSearchResult.cs b/MediaBrowser.Model/Providers/RemoteSearchResult.cs index 8c9e116d60..72b6632e4c 100644 --- a/MediaBrowser.Model/Providers/RemoteSearchResult.cs +++ b/MediaBrowser.Model/Providers/RemoteSearchResult.cs @@ -32,7 +32,8 @@ namespace MediaBrowser.Model.Providers public string SearchProviderName { get; set; } public string GameSystem { get; set; } - + public string Overview { get; set; } + public RemoteSearchResult() { ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index a0ce806105..9ed8f0a007 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -85,7 +85,8 @@ namespace MediaBrowser.Providers.Music { var result = new RemoteSearchResult { - Name = i.Title + Name = i.Title, + ProductionYear = i.Year }; if (!string.IsNullOrWhiteSpace(i.ReleaseId)) @@ -94,7 +95,7 @@ namespace MediaBrowser.Providers.Music } if (!string.IsNullOrWhiteSpace(i.ReleaseGroupId)) { - result.SetProviderId(MetadataProviders.MusicBrainzAlbum, i.ReleaseGroupId); + result.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, i.ReleaseGroupId); } return result; @@ -117,16 +118,22 @@ namespace MediaBrowser.Providers.Music var releaseResult = await GetReleaseResult(artistMusicBrainzId, id.GetAlbumArtist(), id.Name, cancellationToken).ConfigureAwait(false); - if (!string.IsNullOrEmpty(releaseResult.ReleaseId)) + if (releaseResult != null) { - releaseId = releaseResult.ReleaseId; - result.HasMetadata = true; - } + if (!string.IsNullOrEmpty(releaseResult.ReleaseId)) + { + releaseId = releaseResult.ReleaseId; + result.HasMetadata = true; + } - if (!string.IsNullOrEmpty(releaseResult.ReleaseGroupId)) - { - releaseGroupId = releaseResult.ReleaseGroupId; - result.HasMetadata = true; + if (!string.IsNullOrEmpty(releaseResult.ReleaseGroupId)) + { + releaseGroupId = releaseResult.ReleaseGroupId; + result.HasMetadata = true; + } + + result.Item.ProductionYear = releaseResult.Year; + result.Item.Overview = releaseResult.Overview; } } @@ -205,6 +212,8 @@ namespace MediaBrowser.Providers.Music public string ReleaseId; public string ReleaseGroupId; public string Title; + public string Overview; + public int? Year; public static List Parse(XmlDocument doc, int? limit = null) { @@ -237,7 +246,9 @@ namespace MediaBrowser.Providers.Music { ReleaseId = releaseId, ReleaseGroupId = releaseGroupId, - Title = GetTitleFromReleaseNode(node) + Title = GetValueFromReleaseNode(node, "title"), + Overview = GetValueFromReleaseNode(node, "annotation"), + Year = GetYearFromReleaseNode(node, "date") }); if (limit.HasValue && list.Count >= limit.Value) @@ -251,14 +262,37 @@ namespace MediaBrowser.Providers.Music return list; } - private static string GetTitleFromReleaseNode(XmlNode node) + private static int? GetYearFromReleaseNode(XmlNode node, string name) + { + var subNodes = node.ChildNodes; + if (subNodes != null) + { + foreach (var subNode in subNodes.Cast()) + { + if (string.Equals(subNode.Name, name, StringComparison.OrdinalIgnoreCase)) + { + DateTime date; + if (DateTime.TryParse(subNode.InnerText, out date)) + { + return date.Year; + } + + return null; + } + } + } + + return null; + } + + private static string GetValueFromReleaseNode(XmlNode node, string name) { var subNodes = node.ChildNodes; if (subNodes != null) { foreach (var subNode in subNodes.Cast()) { - if (string.Equals(subNode.Name, "title", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(subNode.Name, name, StringComparison.OrdinalIgnoreCase)) { return subNode.InnerText; } diff --git a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs index 88635bf06c..88128bdc7a 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs @@ -86,7 +86,7 @@ namespace MediaBrowser.Providers.Music if (node.Attributes != null) { string name = null; - + string overview = null; string mbzId = node.Attributes["id"].Value; foreach (var child in node.ChildNodes.Cast()) @@ -94,7 +94,10 @@ namespace MediaBrowser.Providers.Music if (string.Equals(child.Name, "name", StringComparison.OrdinalIgnoreCase)) { name = child.InnerText; - break; + } + if (string.Equals(child.Name, "annotation", StringComparison.OrdinalIgnoreCase)) + { + overview = child.InnerText; } } @@ -102,7 +105,8 @@ namespace MediaBrowser.Providers.Music { var result = new RemoteSearchResult { - Name = name + Name = name, + Overview = overview }; result.SetProviderId(MetadataProviders.MusicBrainzArtist, mbzId); @@ -135,6 +139,7 @@ namespace MediaBrowser.Providers.Music { musicBrainzId = singleResult.GetProviderId(MetadataProviders.MusicBrainzArtist); //result.Item.Name = singleResult.Name; + result.Item.Overview = singleResult.Overview; } } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index ae204c892a..47c1d83320 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1432,6 +1432,12 @@ namespace MediaBrowser.Server.Implementations.Dto SetBookProperties(dto, book); } + var movie = item as Movie; + if (movie != null) + { + dto.ProductionLocations = new string[] { }; + } + var photo = item as Photo; if (photo != null) { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 8275b01b00..77e2c36e20 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -742,7 +742,15 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = item.Id; _saveItemCommand.GetParameter(index++).Value = item.GetType().FullName; - _saveItemCommand.GetParameter(index++).Value = _jsonSerializer.SerializeToBytes(item, _memoryStreamProvider); + + if (TypeRequiresDeserialization(item.GetType())) + { + _saveItemCommand.GetParameter(index++).Value = _jsonSerializer.SerializeToBytes(item, _memoryStreamProvider); + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } _saveItemCommand.GetParameter(index++).Value = item.Path; From daaae69df575f1d7692ba29d6f5ddd4c59516f82 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 9 Oct 2016 03:18:43 -0400 Subject: [PATCH 2/2] 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