diff options
45 files changed, 353 insertions, 173 deletions
diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index 331c55f17..c53076829 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -14,14 +14,6 @@ using System.Threading.Tasks; namespace MediaBrowser.Api { - [Route("/LiveTv/Channels/{ChannelId}", "POST")] - [Api(("Updates an item"))] - public class UpdateChannel : BaseItemDto, IReturnVoid - { - [ApiMember(Name = "ChannelId", Description = "The id of the channel", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string ChannelId { get; set; } - } - [Route("/Items/{ItemId}", "POST")] [Api(("Updates an item"))] public class UpdateItem : BaseItemDto, IReturnVoid @@ -98,13 +90,6 @@ namespace MediaBrowser.Api Task.WaitAll(task); } - public void Post(UpdateChannel request) - { - var task = UpdateItem(request); - - Task.WaitAll(task); - } - private async Task UpdateItem(UpdateItem request) { var item = _dtoService.GetItemByDtoId(request.ItemId); @@ -144,15 +129,6 @@ namespace MediaBrowser.Api await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } - private async Task UpdateItem(UpdateChannel request) - { - var item = _liveTv.GetInternalChannel(request.Id); - - UpdateItem(request, item); - - await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - } - public void Post(UpdateArtist request) { var task = UpdateItem(request); @@ -288,6 +264,12 @@ namespace MediaBrowser.Api hasTags.Tags = request.Tags; } + var hasKeywords = item as IHasKeywords; + if (hasKeywords != null) + { + hasKeywords.Keywords = request.Keywords; + } + if (request.Studios != null) { item.Studios = request.Studios.Select(x => x.Name).ToList(); diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 5b123eb97..20b1af8b2 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -13,9 +13,9 @@ using System.Threading.Tasks; namespace MediaBrowser.Api.LiveTv { - [Route("/LiveTv/Services", "GET")] + [Route("/LiveTv/Info", "GET")] [Api(Description = "Gets available live tv services.")] - public class GetServices : IReturn<List<LiveTvServiceInfo>> + public class GetLiveTvInfo : IReturn<LiveTvInfo> { } @@ -290,13 +290,19 @@ namespace MediaBrowser.Api.LiveTv } } - public object Get(GetServices request) + public object Get(GetLiveTvInfo request) { var services = _liveTvManager.Services .Select(GetServiceInfo) .ToList(); - return ToOptimizedResult(services); + var info = new LiveTvInfo + { + Services = services, + ActiveServiceName = _liveTvManager.ActiveService == null ? null : _liveTvManager.ActiveService.Name + }; + + return ToOptimizedResult(info); } private LiveTvServiceInfo GetServiceInfo(ILiveTvService service) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index a39e4cf58..7ad15c9ee 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1004,9 +1004,9 @@ namespace MediaBrowser.Api.Playback RequestedUrl = url }; - Guid itemId; + var item = DtoService.GetItemByDtoId(request.Id); - if (string.Equals(request.Type, "Recording", StringComparison.OrdinalIgnoreCase)) + if (item is ILiveTvRecording) { var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false); @@ -1042,11 +1042,10 @@ namespace MediaBrowser.Api.Playback } } - itemId = recording.Id; //state.RunTimeTicks = recording.RunTimeTicks; state.SendInputOverStandardInput = recording.RecordingInfo.Status == RecordingStatus.InProgress; } - else if (string.Equals(request.Type, "Channel", StringComparison.OrdinalIgnoreCase)) + else if (item is LiveTvChannel) { var channel = LiveTvManager.GetInternalChannel(request.Id); @@ -1069,13 +1068,10 @@ namespace MediaBrowser.Api.Playback state.IsRemote = true; } - itemId = channel.Id; state.SendInputOverStandardInput = true; } else { - var item = DtoService.GetItemByDtoId(request.Id); - state.MediaPath = item.Path; state.IsRemote = item.LocationType == LocationType.Remote; @@ -1093,14 +1089,13 @@ namespace MediaBrowser.Api.Playback } state.RunTimeTicks = item.RunTimeTicks; - itemId = item.Id; } var videoRequest = request as VideoStreamRequest; var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery { - ItemId = itemId + ItemId = item.Id }).ToList(); diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 454cc411c..1486c0de7 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -65,12 +65,6 @@ namespace MediaBrowser.Api.Playback /// No need to put this in api docs since it's dlna only /// </summary> public bool AlbumArt { get; set; } - - /// <summary> - /// Gets or sets the type. - /// </summary> - /// <value>The type.</value> - public string Type { get; set; } } public class VideoStreamRequest : StreamRequest diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs index 683e609d2..d1dc801bc 100644 --- a/MediaBrowser.Api/SimilarItemsHelper.cs +++ b/MediaBrowser.Api/SimilarItemsHelper.cs @@ -130,6 +130,17 @@ namespace MediaBrowser.Api return new List<string>(); } + private static IEnumerable<string> GetKeywords(BaseItem item) + { + var hasTags = item as IHasKeywords; + if (hasTags != null) + { + return hasTags.Keywords; + } + + return new List<string>(); + } + /// <summary> /// Gets the similiarity score. /// </summary> @@ -151,6 +162,9 @@ namespace MediaBrowser.Api // Find common tags points += GetTags(item1).Where(i => GetTags(item2).Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 10); + // Find common keywords + points += GetKeywords(item1).Where(i => GetKeywords(item2).Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 10); + // Find common studios points += item1.Studios.Where(i => item2.Studios.Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 3); diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs index 5c1b10487..48fc72913 100644 --- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs +++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs @@ -114,5 +114,10 @@ namespace MediaBrowser.Api.UserLibrary return LibraryManager.GetAllArtists(items) .Select(name => LibraryManager.GetArtist(name)); } + + protected override IEnumerable<BaseItem> GetLibraryItems(MusicArtist item, IEnumerable<BaseItem> libraryItems) + { + return libraryItems.OfType<IHasArtist>().Where(i => i.HasArtist(item.Name)).Cast<BaseItem>(); + } } } diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index 15926e983..dec35100d 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -93,6 +93,8 @@ namespace MediaBrowser.Api.UserLibrary var filteredItems = FilterItems(request, extractedItems, user); + filteredItems = FilterByLibraryItems(request, filteredItems, user); + filteredItems = ItemsService.ApplySortOrder(request, filteredItems, user, LibraryManager).Cast<TItemType>(); var ibnItemsArray = filteredItems.ToList(); @@ -127,6 +129,39 @@ namespace MediaBrowser.Api.UserLibrary return result; } + private IEnumerable<TItemType> FilterByLibraryItems(GetItemsByName request, IEnumerable<TItemType> items, User user) + { + var filters = request.GetFilters().ToList(); + + if (filters.Contains(ItemFilter.IsPlayed)) + { + var libraryItems = user.RootFolder.GetRecursiveChildren(user).ToList(); + + items = items.Where(i => GetLibraryItems(i, libraryItems).All(l => + { + var userdata = UserDataRepository.GetUserData(user.Id, l.GetUserDataKey()); + + return userdata != null && userdata.Played; + })); + } + + if (filters.Contains(ItemFilter.IsUnplayed)) + { + var libraryItems = user.RootFolder.GetRecursiveChildren(user).ToList(); + + items = items.Where(i => GetLibraryItems(i, libraryItems).All(l => + { + var userdata = UserDataRepository.GetUserData(user.Id, l.GetUserDataKey()); + + return userdata == null || !userdata.Played; + })); + } + + return items; + } + + protected abstract IEnumerable<BaseItem> GetLibraryItems(TItemType item, IEnumerable<BaseItem> libraryItems); + /// <summary> /// Filters the items. /// </summary> diff --git a/MediaBrowser.Api/UserLibrary/GameGenresService.cs b/MediaBrowser.Api/UserLibrary/GameGenresService.cs index 54aeaeed3..79ee27df6 100644 --- a/MediaBrowser.Api/UserLibrary/GameGenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GameGenresService.cs @@ -109,5 +109,10 @@ namespace MediaBrowser.Api.UserLibrary .Distinct(StringComparer.OrdinalIgnoreCase) .Select(name => LibraryManager.GetGameGenre(name)); } + + protected override IEnumerable<BaseItem> GetLibraryItems(GameGenre item, IEnumerable<BaseItem> libraryItems) + { + return libraryItems.Where(i => (i is Game) && i.Genres.Contains(item.Name, StringComparer.OrdinalIgnoreCase)); + } } } diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs index db3948976..d1f7fab01 100644 --- a/MediaBrowser.Api/UserLibrary/GenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GenresService.cs @@ -1,5 +1,6 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; @@ -113,5 +114,10 @@ namespace MediaBrowser.Api.UserLibrary .Distinct(StringComparer.OrdinalIgnoreCase) .Select(name => LibraryManager.GetGenre(name)); } + + protected override IEnumerable<BaseItem> GetLibraryItems(Genre item, IEnumerable<BaseItem> libraryItems) + { + return libraryItems.Where(i => !(i is Game) && !(i is IHasMusicGenres) && i.Genres.Contains(item.Name, StringComparer.OrdinalIgnoreCase)); + } } } diff --git a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs index 59af94ef5..945ac5a67 100644 --- a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs +++ b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs @@ -109,5 +109,10 @@ namespace MediaBrowser.Api.UserLibrary .Distinct(StringComparer.OrdinalIgnoreCase) .Select(name => LibraryManager.GetMusicGenre(name)); } + + protected override IEnumerable<BaseItem> GetLibraryItems(MusicGenre item, IEnumerable<BaseItem> libraryItems) + { + return libraryItems.Where(i => (i is IHasMusicGenres) && i.Genres.Contains(item.Name, StringComparer.OrdinalIgnoreCase)); + } } } diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs index 48e486bb5..03e710ae8 100644 --- a/MediaBrowser.Api/UserLibrary/PersonsService.cs +++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs @@ -163,5 +163,10 @@ namespace MediaBrowser.Api.UserLibrary people.Where(p => personTypes.Contains(p.Type ?? string.Empty, StringComparer.OrdinalIgnoreCase) || personTypes.Contains(p.Role ?? string.Empty, StringComparer.OrdinalIgnoreCase)); } + + protected override IEnumerable<BaseItem> GetLibraryItems(Person item, IEnumerable<BaseItem> libraryItems) + { + return libraryItems.Where(i => i.People.Any(p => string.Equals(p.Name, item.Name, StringComparison.OrdinalIgnoreCase))); + } } } diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs index 86f939437..8b1eeec0f 100644 --- a/MediaBrowser.Api/UserLibrary/StudiosService.cs +++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs @@ -114,5 +114,10 @@ namespace MediaBrowser.Api.UserLibrary .Distinct(StringComparer.OrdinalIgnoreCase) .Select(name => LibraryManager.GetStudio(name)); } + + protected override IEnumerable<BaseItem> GetLibraryItems(Studio item, IEnumerable<BaseItem> libraryItems) + { + return libraryItems.Where(i => i.Studios.Contains(item.Name, StringComparer.OrdinalIgnoreCase)); + } } } diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs index 8f5178ac5..8b03fb50b 100644 --- a/MediaBrowser.Api/UserLibrary/YearsService.cs +++ b/MediaBrowser.Api/UserLibrary/YearsService.cs @@ -114,5 +114,19 @@ namespace MediaBrowser.Api.UserLibrary .Distinct() .Select(year => LibraryManager.GetYear(year)); } + + protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + protected override IEnumerable<BaseItem> GetLibraryItems(Year item, IEnumerable<BaseItem> libraryItems) + { + int year; + + if (!int.TryParse(item.Name, NumberStyles.Integer, UsCulture, out year)) + { + return libraryItems; + } + + return libraryItems.Where(i => i.ProductionYear.HasValue && i.ProductionYear.Value == year); + } } } diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index 6cd10a2fb..fd5ccac5b 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -58,6 +58,13 @@ namespace MediaBrowser.Controller.Dto BaseItem GetItemByDtoId(string id, Guid? userId = null); /// <summary> + /// Attaches the primary image aspect ratio. + /// </summary> + /// <param name="dto">The dto.</param> + /// <param name="item">The item.</param> + void AttachPrimaryImageAspectRatio(IItemDto dto, IHasImages item); + + /// <summary> /// Gets the base item dto. /// </summary> /// <param name="item">The item.</param> diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index dcee4bae7..c887f6977 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -505,28 +505,6 @@ namespace MediaBrowser.Controller.Entities public List<PersonInfo> People { get; set; } /// <summary> - /// Override this if you need to combine/collapse person information - /// </summary> - /// <value>All people.</value> - [IgnoreDataMember] - public virtual IEnumerable<PersonInfo> AllPeople - { - get { return People; } - } - - [IgnoreDataMember] - public virtual IEnumerable<string> AllStudios - { - get { return Studios; } - } - - [IgnoreDataMember] - public virtual IEnumerable<string> AllGenres - { - get { return Genres; } - } - - /// <summary> /// Gets or sets the studios. /// </summary> /// <value>The studios.</value> @@ -662,7 +640,7 @@ namespace MediaBrowser.Controller.Entities return LibraryManager.ResolvePaths<Trailer>(files, null).Select(video => { // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = LibraryManager.RetrieveItem(video.Id) as Trailer; + var dbItem = LibraryManager.GetItemById(video.Id) as Trailer; if (dbItem != null) { @@ -723,7 +701,7 @@ namespace MediaBrowser.Controller.Entities return LibraryManager.ResolvePaths<Audio.Audio>(files, null).Select(audio => { // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = LibraryManager.RetrieveItem(audio.Id) as Audio.Audio; + var dbItem = LibraryManager.GetItemById(audio.Id) as Audio.Audio; if (dbItem != null) { @@ -781,7 +759,7 @@ namespace MediaBrowser.Controller.Entities return LibraryManager.ResolvePaths<Video>(files, null).Select(item => { // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = LibraryManager.RetrieveItem(item.Id) as Video; + var dbItem = LibraryManager.GetItemById(item.Id) as Video; if (dbItem != null) { diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index a85157a26..6fb99f547 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -884,7 +884,7 @@ namespace MediaBrowser.Controller.Entities // First get using the cached Id if (info.ItemId != Guid.Empty) { - item = LibraryManager.GetItemById(info.ItemId); + item = LibraryManager.GetItemById(info.ItemId) as BaseItem; } // If still null, search by path diff --git a/MediaBrowser.Controller/Entities/IHasKeywords.cs b/MediaBrowser.Controller/Entities/IHasKeywords.cs new file mode 100644 index 000000000..ab9eb4aee --- /dev/null +++ b/MediaBrowser.Controller/Entities/IHasKeywords.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MediaBrowser.Controller.Entities +{ + public interface IHasKeywords + { + /// <summary> + /// Gets or sets the keywords. + /// </summary> + /// <value>The keywords.</value> + List<string> Keywords { get; set; } + } + + public static class KeywordExtensions + { + public static void AddKeyword(this IHasKeywords item, string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentNullException("name"); + } + + if (!item.Keywords.Contains(name, StringComparer.OrdinalIgnoreCase)) + { + item.Keywords.Add(name); + } + } + } +} diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 91e7873c8..19d0d6682 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Controller.Entities.Movies /// <summary> /// Class BoxSet /// </summary> - public class BoxSet : Folder, IHasTrailers, IHasTags, IHasPreferredMetadataLanguage, IHasDisplayOrder + public class BoxSet : Folder, IHasTrailers, IHasTags, IHasKeywords, IHasPreferredMetadataLanguage, IHasDisplayOrder { public BoxSet() { @@ -18,6 +18,7 @@ namespace MediaBrowser.Controller.Entities.Movies Tags = new List<string>(); DisplayOrder = ItemSortBy.PremiereDate; + Keywords = new List<string>(); } public List<Guid> LocalTrailerIds { get; set; } @@ -33,6 +34,7 @@ namespace MediaBrowser.Controller.Entities.Movies /// </summary> /// <value>The tags.</value> public List<string> Tags { get; set; } + public List<string> Keywords { get; set; } public string PreferredMetadataLanguage { get; set; } diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index f9d3f845c..ba11b0eef 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities.Movies /// <summary> /// Class Movie /// </summary> - public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasTags, IHasPreferredMetadataLanguage + public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasTags, IHasPreferredMetadataLanguage { public List<Guid> SpecialFeatureIds { get; set; } @@ -39,10 +39,12 @@ namespace MediaBrowser.Controller.Entities.Movies ThemeVideoIds = new List<Guid>(); Taglines = new List<string>(); Tags = new List<string>(); + Keywords = new List<string>(); } public List<Guid> LocalTrailerIds { get; set; } - + public List<string> Keywords { get; set; } + public List<MediaUrl> RemoteTrailers { get; set; } /// <summary> @@ -177,7 +179,7 @@ namespace MediaBrowser.Controller.Entities.Movies return LibraryManager.ResolvePaths<Video>(files, null).Select(video => { // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = LibraryManager.RetrieveItem(video.Id) as Video; + var dbItem = LibraryManager.GetItemById(video.Id) as Video; if (dbItem != null) { diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 42897e09f..61bf14543 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -123,48 +123,6 @@ namespace MediaBrowser.Controller.Entities.TV } /// <summary> - /// Override this if you need to combine/collapse person information - /// </summary> - /// <value>All people.</value> - [IgnoreDataMember] - public override IEnumerable<PersonInfo> AllPeople - { - get - { - if (People == null) return Series != null ? Series.People : People; - return Series != null && Series.People != null ? People.Concat(Series.People) : base.AllPeople; - } - } - - /// <summary> - /// Gets all genres. - /// </summary> - /// <value>All genres.</value> - [IgnoreDataMember] - public override IEnumerable<string> AllGenres - { - get - { - if (Genres == null) return Series != null ? Series.Genres : Genres; - return Series != null && Series.Genres != null ? Genres.Concat(Series.Genres) : base.AllGenres; - } - } - - /// <summary> - /// Gets all studios. - /// </summary> - /// <value>All studios.</value> - [IgnoreDataMember] - public override IEnumerable<string> AllStudios - { - get - { - if (Studios == null) return Series != null ? Series.Studios : Studios; - return Series != null && Series.Studios != null ? Studios.Concat(Series.Studios) : base.AllStudios; - } - } - - /// <summary> /// Our rating comes from our series /// </summary> [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 7000d04d3..39869505c 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class Trailer /// </summary> - public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers, IHasTaglines, IHasTags, IHasPreferredMetadataLanguage + public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers, IHasKeywords, IHasTaglines, IHasTags, IHasPreferredMetadataLanguage { public List<Guid> SoundtrackIds { get; set; } @@ -28,12 +28,15 @@ namespace MediaBrowser.Controller.Entities SoundtrackIds = new List<Guid>(); LocalTrailerIds = new List<Guid>(); Tags = new List<string>(); + Keywords = new List<string>(); } public List<Guid> LocalTrailerIds { get; set; } public List<MediaUrl> RemoteTrailers { get; set; } + public List<string> Keywords { get; set; } + /// <summary> /// Gets or sets the tags. /// </summary> diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 8ca475650..e663c8353 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -268,7 +268,7 @@ namespace MediaBrowser.Controller.Entities return LibraryManager.ResolvePaths<Video>(files, null).Select(video => { // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = LibraryManager.RetrieveItem(video.Id) as Video; + var dbItem = LibraryManager.GetItemById(video.Id) as Video; if (dbItem != null) { diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index c34180eb6..c45c14239 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -35,7 +35,17 @@ namespace MediaBrowser.Controller.Library /// <value>The file system children.</value> public IEnumerable<FileSystemInfo> FileSystemChildren { - get { return FileSystemDictionary.Values; } + get + { + var dict = FileSystemDictionary; + + if (dict == null) + { + return new List<FileSystemInfo>(); + } + + return dict.Values; + } } /// <summary> diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 14205e668..af3857f17 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -87,6 +87,7 @@ <Compile Include="Entities\IHasCriticRating.cs" /> <Compile Include="Entities\IHasDisplayOrder.cs" /> <Compile Include="Entities\IHasImages.cs" /> + <Compile Include="Entities\IHasKeywords.cs" /> <Compile Include="Entities\IHasMediaStreams.cs" /> <Compile Include="Entities\IHasPreferredMetadataLanguage.cs" /> <Compile Include="Entities\IHasProductionLocations.cs" /> diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index ea21e18b0..72cb0d73e 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -79,6 +79,11 @@ namespace MediaBrowser.Controller.Providers hasTags.Tags.Clear(); } + var hasKeywords = item as IHasKeywords; + if (hasKeywords != null) + { + hasKeywords.Keywords.Clear(); + } var hasTrailers = item as IHasTrailers; if (hasTrailers != null) @@ -747,6 +752,19 @@ namespace MediaBrowser.Controller.Providers break; } + case "PlotKeywords": + { + using (var subtree = reader.ReadSubtree()) + { + var hasTags = item as IHasKeywords; + if (hasTags != null) + { + FetchFromKeywordsNode(subtree, hasTags); + } + } + break; + } + case "Persons": { using (var subtree = reader.ReadSubtree()) @@ -912,6 +930,35 @@ namespace MediaBrowser.Controller.Providers } } + private void FetchFromKeywordsNode(XmlReader reader, IHasKeywords item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "PlotKeyword": + { + var tag = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(tag)) + { + item.AddKeyword(tag); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + /// <summary> /// Fetches the data from persons node. /// </summary> diff --git a/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs b/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs index 0c4dbfd65..98e99b1cc 100644 --- a/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs +++ b/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs @@ -1,7 +1,7 @@ -using System.IO; +using MediaBrowser.Model.Dto; +using System.IO; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Dto; namespace MediaBrowser.Model.ApiClient { diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index af43ef200..cc20cc95f 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -371,6 +371,12 @@ namespace MediaBrowser.Model.Dto public List<string> Tags { get; set; } /// <summary> + /// Gets or sets the keywords. + /// </summary> + /// <value>The keywords.</value> + public List<string> Keywords { get; set; } + + /// <summary> /// Gets or sets the primary image aspect ratio, after image enhancements. /// </summary> /// <value>The primary image aspect ratio.</value> diff --git a/MediaBrowser.Model/Entities/MetadataFields.cs b/MediaBrowser.Model/Entities/MetadataFields.cs index a99fd0fe0..a6c1388dc 100644 --- a/MediaBrowser.Model/Entities/MetadataFields.cs +++ b/MediaBrowser.Model/Entities/MetadataFields.cs @@ -15,6 +15,10 @@ namespace MediaBrowser.Model.Entities /// </summary> Genres, /// <summary> + /// The keywords + /// </summary> + Keywords, + /// <summary> /// The production locations /// </summary> ProductionLocations, diff --git a/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs b/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs index 7ee86ffac..afce04230 100644 --- a/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs @@ -8,7 +8,7 @@ namespace MediaBrowser.Model.LiveTv /// <summary> /// Class ChannelInfoDto /// </summary> - public class ChannelInfoDto + public class ChannelInfoDto : IItemDto { /// <summary> /// Gets or sets the name. @@ -76,6 +76,18 @@ namespace MediaBrowser.Model.LiveTv /// <value>The now playing program.</value> public ProgramInfoDto CurrentProgram { get; set; } + /// <summary> + /// Gets or sets the primary image aspect ratio, after image enhancements. + /// </summary> + /// <value>The primary image aspect ratio.</value> + public double? PrimaryImageAspectRatio { get; set; } + + /// <summary> + /// Gets or sets the primary image aspect ratio, before image enhancements. + /// </summary> + /// <value>The original primary image aspect ratio.</value> + public double? OriginalPrimaryImageAspectRatio { get; set; } + public ChannelInfoDto() { ImageTags = new Dictionary<ImageType, Guid>(); diff --git a/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs b/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs index a25207509..c93779b5a 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace MediaBrowser.Model.LiveTv { @@ -28,4 +29,24 @@ namespace MediaBrowser.Model.LiveTv /// <value>The end date.</value> public DateTime EndDate { get; set; } } + + public class LiveTvInfo + { + /// <summary> + /// Gets or sets the services. + /// </summary> + /// <value>The services.</value> + public List<LiveTvServiceInfo> Services { get; set; } + + /// <summary> + /// Gets or sets the name of the active service. + /// </summary> + /// <value>The name of the active service.</value> + public string ActiveServiceName { get; set; } + + public LiveTvInfo() + { + Services = new List<LiveTvServiceInfo>(); + } + } } diff --git a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs index 389df2248..c1161f4ec 100644 --- a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs @@ -107,7 +107,13 @@ namespace MediaBrowser.Model.LiveTv /// </summary> /// <value>The name of the status.</value> public string StatusName { get; set; } - + + /// <summary> + /// Gets or sets the completion percentage. + /// </summary> + /// <value>The completion percentage.</value> + public double? CompletionPercentage { get; set; } + /// <summary> /// Genre of the program. /// </summary> diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index 6d61d8ac7..46123485e 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -57,6 +57,11 @@ namespace MediaBrowser.Model.Querying IndexOptions, /// <summary> + /// The keywords + /// </summary> + Keywords, + + /// <summary> /// The metadata settings /// </summary> Settings, diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs index fc2c5c370..640dbd3fa 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs @@ -251,7 +251,9 @@ namespace MediaBrowser.Providers.MediaInfo // Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size // Once we reach a file that is at least the minimum, return all subsequent ones - var allVobs = Directory.EnumerateFiles(root, "*.vob", SearchOption.AllDirectories).ToList(); + var allVobs = Directory.EnumerateFiles(root, "*", SearchOption.AllDirectories) + .Where(file => string.Equals(Path.GetExtension(file), ".vob", StringComparison.OrdinalIgnoreCase)) + .ToList(); // If we didn't find any satisfying the min length, just take them all if (allVobs.Count == 0) diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 8dd64fd14..d4367a5db 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -847,14 +847,14 @@ namespace MediaBrowser.Providers.Movies } } - //if (movieData.keywords != null && movieData.keywords.keywords != null && !movie.LockedFields.Contains(MetadataFields.Tags)) - //{ - // var hasTags = movie as IHasTags; - // if (hasTags != null) - // { - // hasTags.Tags = movieData.keywords.keywords.Select(i => i.name).ToList(); - // } - //} + if (movieData.keywords != null && movieData.keywords.keywords != null && !movie.LockedFields.Contains(MetadataFields.Keywords)) + { + var hasTags = movie as IHasKeywords; + if (hasTags != null) + { + hasTags.Keywords = movieData.keywords.keywords.Select(i => i.name).ToList(); + } + } if (movieData.trailers != null && movieData.trailers.youtube != null && movieData.trailers.youtube.Count > 0) diff --git a/MediaBrowser.Providers/RefreshIntrosTask.cs b/MediaBrowser.Providers/RefreshIntrosTask.cs index 3ecddf613..b20a6e331 100644 --- a/MediaBrowser.Providers/RefreshIntrosTask.cs +++ b/MediaBrowser.Providers/RefreshIntrosTask.cs @@ -89,7 +89,7 @@ namespace MediaBrowser.Providers return; } - var dbItem = _libraryManager.RetrieveItem(item.Id); + var dbItem = _libraryManager.GetItemById(item.Id); var isNewItem = false; if (dbItem != null) diff --git a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs index c4bd86a79..c251c139c 100644 --- a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs +++ b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs @@ -484,6 +484,22 @@ namespace MediaBrowser.Providers.Savers } } + var hasKeywords = item as IHasKeywords; + if (hasKeywords != null) + { + if (hasKeywords.Keywords.Count > 0) + { + builder.Append("<PlotKeywords>"); + + foreach (var tag in hasKeywords.Keywords) + { + builder.Append("<PlotKeyword>" + SecurityElement.Escape(tag) + "</PlotKeyword>"); + } + + builder.Append("</PlotKeywords>"); + } + } + if (item.People.Count > 0) { builder.Append("<Persons>"); diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 59accba1f..9cf21c534 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -131,11 +131,10 @@ namespace MediaBrowser.Server.Implementations.Dto { if (user == null) { - //counts = item.ItemCounts; return; } - ItemByNameCounts counts = item.GetItemByNameCounts(user.Id) ?? new ItemByNameCounts(); + var counts = item.GetItemByNameCounts(user.Id) ?? new ItemByNameCounts(); dto.ChildCount = counts.TotalCount; @@ -698,6 +697,20 @@ namespace MediaBrowser.Server.Implementations.Dto } } + if (fields.Contains(ItemFields.Keywords)) + { + var hasTags = item as IHasKeywords; + if (hasTags != null) + { + dto.Keywords = hasTags.Keywords; + } + + if (dto.Keywords == null) + { + dto.Keywords = new List<string>(); + } + } + if (fields.Contains(ItemFields.ProductionLocations)) { SetProductionLocations(item, dto); @@ -1230,7 +1243,7 @@ namespace MediaBrowser.Server.Implementations.Dto /// <param name="dto">The dto.</param> /// <param name="item">The item.</param> /// <returns>Task.</returns> - private void AttachPrimaryImageAspectRatio(IItemDto dto, BaseItem item) + public void AttachPrimaryImageAspectRatio(IItemDto dto, IHasImages item) { var path = item.PrimaryImagePath; diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs index ad9f769eb..55fa47ff7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -231,6 +231,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv }).ToList() }; + if (info.Status == RecordingStatus.InProgress) + { + var now = DateTime.UtcNow.Ticks; + var start = info.StartDate.Ticks; + var end = info.EndDate.Ticks; + + var pct = now - start; + pct /= end; + pct *= 100; + dto.CompletionPercentage = pct; + } + var imageTag = GetImageTag(recording); if (imageTag.HasValue) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index b53b3b651..eff919f17 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1045,13 +1045,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv info.DayPattern = _tvDtoService.GetDayPattern(info.Days); info.Name = program.Name; - info.ChannelId = program.ChannelId; + info.ChannelId = programDto.ChannelId; info.ChannelName = programDto.ChannelName; info.EndDate = program.EndDate; info.StartDate = program.StartDate; info.Name = program.Name; info.Overview = program.Overview; - info.ProgramId = program.Id; + info.ProgramId = programDto.Id; info.ExternalProgramId = programDto.ExternalId; return info; diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs index 7ac15dff9..0de65f479 100644 --- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg // Mac OS X Intel 64bit return new[] { - "https://copy.com/ylAUbbQHYE7x/ffall-2.1.1.7z?download=1" + "https://copy.com/IB0W4efS6t9A/ffall-2.1.1.tar.gz?download=1" }; } else diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js index 578f71176..e790a1836 100644 --- a/MediaBrowser.WebDashboard/ApiClient.js +++ b/MediaBrowser.WebDashboard/ApiClient.js @@ -378,20 +378,9 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi }); }; - self.getAuthorizedFeatures = function (options) { + self.getLiveTvInfo = function (options) { - var url = self.getUrl("Users/AuthorizedFeatures", options || {}); - - return self.ajax({ - type: "GET", - url: url, - dataType: "json" - }); - }; - - self.getLiveTvServices = function (options) { - - var url = self.getUrl("LiveTv/Services", options || {}); + var url = self.getUrl("LiveTv/Info", options || {}); return self.ajax({ type: "GET", @@ -2714,22 +2703,6 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi }); }; - self.updateLiveTvChannel = function (item) { - - if (!item) { - throw new Error("null item"); - } - - var url = self.getUrl("LiveTv/Channels/" + item.Id); - - return self.ajax({ - type: "POST", - url: url, - data: JSON.stringify(item), - contentType: "application/json" - }); - }; - self.updateArtist = function (item) { if (!item) { diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index 939ca9997..56158ace7 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="MediaBrowser.ApiClient.Javascript" version="3.0.228" targetFramework="net45" /> + <package id="MediaBrowser.ApiClient.Javascript" version="3.0.230" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index dd0a06615..e325c9804 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common.Internal</id> - <version>3.0.300</version> + <version>3.0.301</version> <title>MediaBrowser.Common.Internal</title> <authors>Luke</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.300" /> + <dependency id="MediaBrowser.Common" version="3.0.301" /> <dependency id="NLog" version="2.1.0" /> <dependency id="SimpleInjector" version="2.4.0" /> <dependency id="sharpcompress" version="0.10.2" /> diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 72fc2ac63..4a8b2f700 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.300</version> + <version>3.0.301</version> <title>MediaBrowser.Common</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index f5db426ca..9cbcf30a4 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Server.Core</id> - <version>3.0.300</version> + <version>3.0.301</version> <title>Media Browser.Server.Core</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains core components required to build plugins for Media Browser Server.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.300" /> + <dependency id="MediaBrowser.Common" version="3.0.301" /> </dependencies> </metadata> <files> |
