diff options
22 files changed, 355 insertions, 103 deletions
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 3360d9736..f9b760869 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -106,7 +106,10 @@ namespace MediaBrowser.Api.Movies _userDataRepository, _dtoService, Logger, - request, item => item is Movie || (item is Trailer && request.IncludeTrailers), + + // Strip out secondary versions + request, item => (item is Movie || (item is Trailer && request.IncludeTrailers)) && !((Video)item).PrimaryVersionId.HasValue, + SimilarItemsHelper.GetSimiliarityScore); return ToOptimizedSerializedResultUsingCache(result); diff --git a/MediaBrowser.Api/Movies/TrailersService.cs b/MediaBrowser.Api/Movies/TrailersService.cs index 4e17bc7b5..057506635 100644 --- a/MediaBrowser.Api/Movies/TrailersService.cs +++ b/MediaBrowser.Api/Movies/TrailersService.cs @@ -66,7 +66,10 @@ namespace MediaBrowser.Api.Movies _userDataRepository, _dtoService, Logger, - request, item => item is Movie || item is Trailer, + + // Strip out secondary versions + request, item => (item is Movie || item is Trailer) && !((Video)item).PrimaryVersionId.HasValue, + SimilarItemsHelper.GetSimiliarityScore); return ToOptimizedSerializedResultUsingCache(result); diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 9e58c9f53..a805b7b55 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -532,6 +532,8 @@ namespace MediaBrowser.Api var fields = request.GetItemFields().ToList(); + episodes = _libraryManager.ReplaceVideosWithPrimaryVersions(episodes).Cast<Episode>(); + var returnItems = episodes.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .ToArray(); diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index f70a21eaf..a787684bb 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -392,12 +392,16 @@ namespace MediaBrowser.Api.UserLibrary items = user == null ? ((Folder)item).RecursiveChildren : ((Folder)item).GetRecursiveChildren(user); + + items = _libraryManager.ReplaceVideosWithPrimaryVersions(items); } else { items = user == null ? ((Folder)item).Children : ((Folder)item).GetChildren(user, true); + + items = _libraryManager.ReplaceVideosWithPrimaryVersions(items); } if (request.IncludeIndexContainers) diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs index ba3b0912b..476ea405c 100644 --- a/MediaBrowser.Api/VideosService.cs +++ b/MediaBrowser.Api/VideosService.cs @@ -1,13 +1,18 @@ -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using ServiceStack; using System; +using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Api { @@ -26,28 +31,10 @@ namespace MediaBrowser.Api public string Id { get; set; } } - [Route("/Videos/{Id}/AlternateVersions", "GET")] - [Api(Description = "Gets alternate versions of a video.")] - public class GetAlternateVersions : IReturn<ItemsResult> + [Route("/Videos/{Id}/Versions", "GET")] + [Api(Description = "Gets all versions of a video.")] + public class GetMediaVersions : IReturn<List<MediaVersionInfo>> { - [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid? UserId { get; set; } - - /// <summary> - /// Gets or sets the id. - /// </summary> - /// <value>The id.</value> - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - [Route("/Videos/{Id}/AlternateVersions", "POST")] - [Api(Description = "Assigns videos as alternates of antoher.")] - public class PostAlternateVersions : IReturnVoid - { - [ApiMember(Name = "AlternateVersionIds", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string AlternateVersionIds { get; set; } - /// <summary> /// Gets or sets the id. /// </summary> @@ -60,18 +47,16 @@ namespace MediaBrowser.Api [Api(Description = "Assigns videos as alternates of antoher.")] public class DeleteAlternateVersions : IReturnVoid { - [ApiMember(Name = "AlternateVersionIds", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] - public string AlternateVersionIds { get; set; } - - /// <summary> - /// Gets or sets the id. - /// </summary> - /// <value>The id.</value> - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] public string Id { get; set; } + } - [ApiMember(Name = "IsAlternateEncoding", Description = "Filter by versions that are considered alternate encodings of the original.", IsRequired = true, DataType = "bool", ParameterType = "path", Verb = "GET")] - public bool? IsAlternateEncoding { get; set; } + [Route("/Videos/MergeVersions", "POST")] + [Api(Description = "Merges videos into a single record")] + public class MergeVersions : IReturnVoid + { + [ApiMember(Name = "Ids", Description = "Item id list. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] + public string Ids { get; set; } } public class VideosService : BaseApiService @@ -79,12 +64,18 @@ namespace MediaBrowser.Api private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDtoService _dtoService; + private readonly IFileSystem _fileSystem; + private readonly IItemRepository _itemRepo; + private readonly IServerConfigurationManager _config; - public VideosService(ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService) + public VideosService(ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService, IItemRepository itemRepo, IFileSystem fileSystem, IServerConfigurationManager config) { _libraryManager = libraryManager; _userManager = userManager; _dtoService = dtoService; + _itemRepo = itemRepo; + _fileSystem = fileSystem; + _config = config; } /// <summary> @@ -122,90 +113,249 @@ namespace MediaBrowser.Api return ToOptimizedSerializedResultUsingCache(result); } - public object Get(GetAlternateVersions request) + public object Get(GetMediaVersions request) { - var user = request.UserId.HasValue ? _userManager.GetUserById(request.UserId.Value) : null; + var item = _libraryManager.GetItemById(new Guid(request.Id)); - var item = string.IsNullOrEmpty(request.Id) - ? (request.UserId.HasValue - ? user.RootFolder - : _libraryManager.RootFolder) - : _dtoService.GetItemByDtoId(request.Id, request.UserId); + var video = (Video)item; - // Get everything - var fields = Enum.GetNames(typeof(ItemFields)) - .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)) - .ToList(); + var result = video.GetAlternateVersions().Select(GetVersionInfo).ToList(); - var video = (Video)item; + result.Add(GetVersionInfo(video)); - var items = video.GetAlternateVersions() - .Select(i => _dtoService.GetBaseItemDto(i, fields, user, video)) - .ToArray(); + result = result.OrderBy(i => + { + if (video.VideoType == VideoType.VideoFile) + { + return 0; + } - var result = new ItemsResult + return 1; + + }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) + .ThenByDescending(i => { - Items = items, - TotalRecordCount = items.Length - }; + var stream = i.MediaStreams.FirstOrDefault(m => m.Type == MediaStreamType.Video); + + return stream == null || stream.Width == null ? 0 : stream.Width.Value; + }) + .ToList(); return ToOptimizedSerializedResultUsingCache(result); } - public void Post(PostAlternateVersions request) + private MediaVersionInfo GetVersionInfo(Video i) { - var task = AddAlternateVersions(request); - - Task.WaitAll(task); + return new MediaVersionInfo + { + Chapters = _itemRepo.GetChapters(i.Id).Select(c => _dtoService.GetChapterInfoDto(c, i)).ToList(), + + Id = i.Id.ToString("N"), + IsoType = i.IsoType, + LocationType = i.LocationType, + MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery {ItemId = i.Id}).ToList(), + Name = GetAlternateVersionName(i), + Path = GetMappedPath(i), + RunTimeTicks = i.RunTimeTicks, + Video3DFormat = i.Video3DFormat, + VideoType = i.VideoType, + IsHD = i.IsHD + }; } - public void Delete(DeleteAlternateVersions request) + private string GetMappedPath(Video video) { - var task = RemoveAlternateVersions(request); + var path = video.Path; - Task.WaitAll(task); + var locationType = video.LocationType; + + if (locationType != LocationType.FileSystem && locationType != LocationType.Offline) + { + return path; + } + + foreach (var map in _config.Configuration.PathSubstitutions) + { + path = _fileSystem.SubstitutePath(path, map.From, map.To); + } + + return path; } - private async Task AddAlternateVersions(PostAlternateVersions request) + private string GetAlternateVersionName(Video video) { - var video = (Video)_dtoService.GetItemByDtoId(request.Id); + var name = ""; - var list = new List<LinkedChild>(); - var currentAlternateVersions = video.GetAlternateVersions().ToList(); + var stream = video.GetDefaultVideoStream(); - foreach (var itemId in request.AlternateVersionIds.Split(',').Select(i => new Guid(i))) + if (video.Video3DFormat.HasValue) { - var item = _libraryManager.GetItemById(itemId) as Video; + name = "3D " + name; + name = name.Trim(); + } - if (item == null) + if (video.VideoType == VideoType.BluRay) + { + name = name + " " + "Bluray"; + name = name.Trim(); + } + else if (video.VideoType == VideoType.Dvd) + { + name = name + " " + "DVD"; + name = name.Trim(); + } + else if (video.VideoType == VideoType.HdDvd) + { + name = name + " " + "HD-DVD"; + name = name.Trim(); + } + else if (video.VideoType == VideoType.Iso) + { + if (video.IsoType.HasValue) { - throw new ArgumentException("No item exists with the supplied Id"); + if (video.IsoType.Value == IsoType.BluRay) + { + name = name + " " + "Bluray"; + } + else if (video.IsoType.Value == IsoType.Dvd) + { + name = name + " " + "DVD"; + } } - - if (currentAlternateVersions.Any(i => i.Id == itemId)) + else { - throw new ArgumentException("Item already exists."); + name = name + " " + "ISO"; } - - list.Add(new LinkedChild + name = name.Trim(); + } + else if (video.VideoType == VideoType.VideoFile) + { + if (stream != null) { - Path = item.Path, - Type = LinkedChildType.Manual - }); + if (stream.Width.HasValue) + { + if (stream.Width.Value >= 1900) + { + name = name + " " + "1080P"; + name = name.Trim(); + } + else if (stream.Width.Value >= 1270) + { + name = name + " " + "720P"; + name = name.Trim(); + } + else if (stream.Width.Value >= 700) + { + name = name + " " + "480p"; + name = name.Trim(); + } + else + { + name = name + " " + "SD"; + name = name.Trim(); + } + } + } + } - item.PrimaryVersionId = video.Id; + if (stream != null && !string.IsNullOrWhiteSpace(stream.Codec)) + { + name = name + " " + stream.Codec.ToUpper(); + name = name.Trim(); } - video.LinkedAlternateVersions.AddRange(list); + if (string.IsNullOrWhiteSpace(name)) + { + return video.Name; + } - await video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + return name; + } + + public void Delete(DeleteAlternateVersions request) + { + var task = RemoveAlternateVersions(request); - await video.RefreshMetadata(CancellationToken.None).ConfigureAwait(false); + Task.WaitAll(task); } private async Task RemoveAlternateVersions(DeleteAlternateVersions request) { var video = (Video)_dtoService.GetItemByDtoId(request.Id); + + foreach (var link in video.GetLinkedAlternateVersions()) + { + link.PrimaryVersionId = null; + + await link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + } + + video.LinkedAlternateVersions.Clear(); + await video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + } + + public void Post(MergeVersions request) + { + var task = MergeVersions(request); + + Task.WaitAll(task); + } + + private async Task MergeVersions(MergeVersions request) + { + var items = request.Ids.Split(',') + .Select(i => new Guid(i)) + .Select(i => _libraryManager.GetItemById(i)) + .ToList(); + + if (items.Count < 2) + { + throw new ArgumentException("Please supply at least two videos to merge."); + } + + if (items.Any(i => !(i is Video))) + { + throw new ArgumentException("Only videos can be grouped together."); + } + + var videos = items.Cast<Video>().ToList(); + + var videosWithVersions = videos.Where(i => i.AlternateVersionCount > 0) + .ToList(); + + if (videosWithVersions.Count > 1) + { + throw new ArgumentException("Videos with sub-versions cannot be merged."); + } + + var primaryVersion = videosWithVersions.FirstOrDefault(); + + if (primaryVersion == null) + { + primaryVersion = videos.OrderByDescending(i => + { + var stream = i.GetDefaultVideoStream(); + + return stream == null || stream.Width == null ? 0 : stream.Width.Value; + + }).ThenBy(i => i.Name.Length) + .First(); + } + + foreach (var item in videos.Where(i => i.Id != primaryVersion.Id)) + { + item.PrimaryVersionId = primaryVersion.Id; + + await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + + primaryVersion.LinkedAlternateVersions.Add(new LinkedChild + { + Path = item.Path, + ItemId = item.Id + }); + } + + await primaryVersion.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } } } diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs index 269a95456..6f3398f52 100644 --- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs +++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs @@ -2,7 +2,7 @@ namespace MediaBrowser.Controller.Channels { - public class ChannelAudioItem : Audio, IChannelItem + public class ChannelAudioItem : Audio, IChannelMediaItem { public string ExternalId { get; set; } diff --git a/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs b/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs index 11e56ee07..61b38c2b1 100644 --- a/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs +++ b/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs @@ -2,7 +2,12 @@ namespace MediaBrowser.Controller.Channels { - public class ChannelCategoryItem : Folder + public class ChannelCategoryItem : Folder, IChannelItem { + public string ExternalId { get; set; } + + public ChannelItemType ChannelItemType { get; set; } + + public string OriginalImageUrl { get; set; } } } diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs index baa4c2a17..83b85794d 100644 --- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs +++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs @@ -2,7 +2,7 @@ namespace MediaBrowser.Controller.Channels { - public class ChannelVideoItem : Video, IChannelItem + public class ChannelVideoItem : Video, IChannelMediaItem { public string ExternalId { get; set; } diff --git a/MediaBrowser.Controller/Channels/IChannelItem.cs b/MediaBrowser.Controller/Channels/IChannelItem.cs index ffef532a9..a05ef8e29 100644 --- a/MediaBrowser.Controller/Channels/IChannelItem.cs +++ b/MediaBrowser.Controller/Channels/IChannelItem.cs @@ -8,10 +8,13 @@ namespace MediaBrowser.Controller.Channels ChannelItemType ChannelItemType { get; set; } + string OriginalImageUrl { get; set; } + } + + public interface IChannelMediaItem : IChannelItem + { bool IsInfiniteStream { get; set; } ChannelMediaContentType ContentType { get; set; } - - string OriginalImageUrl { get; set; } } } diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index 606b51628..03039dc83 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -85,6 +85,14 @@ namespace MediaBrowser.Controller.Dto where T : BaseItem, IItemByName; /// <summary> + /// Gets the chapter information dto. + /// </summary> + /// <param name="chapterInfo">The chapter information.</param> + /// <param name="item">The item.</param> + /// <returns>ChapterInfoDto.</returns> + ChapterInfoDto GetChapterInfoDto(ChapterInfo chapterInfo, BaseItem item); + + /// <summary> /// Gets the item by name dto. /// </summary> /// <param name="item">The item.</param> diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 18db21f38..25f47aead 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -51,19 +51,25 @@ namespace MediaBrowser.Controller.Entities /// Gets the linked children. /// </summary> /// <returns>IEnumerable{BaseItem}.</returns> - public IEnumerable<BaseItem> GetAlternateVersions() + public IEnumerable<Video> GetAlternateVersions() { var filesWithinSameDirectory = LocalAlternateVersionIds .Select(i => LibraryManager.GetItemById(i)) .Where(i => i != null) .OfType<Video>(); + return filesWithinSameDirectory.Concat(GetLinkedAlternateVersions()) + .OrderBy(i => i.SortName); + } + + public IEnumerable<Video> GetLinkedAlternateVersions() + { var linkedVersions = LinkedAlternateVersions .Select(GetLinkedChild) .Where(i => i != null) .OfType<Video>(); - return filesWithinSameDirectory.Concat(linkedVersions) + return linkedVersions .OrderBy(i => i.SortName); } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 9bde9aa29..680317237 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -324,6 +324,13 @@ namespace MediaBrowser.Controller.Library /// <param name="options">The options.</param> /// <returns>Task.</returns> Task DeleteItem(BaseItem item, DeleteOptions options); + + /// <summary> + /// Replaces the videos with primary versions. + /// </summary> + /// <param name="items">The items.</param> + /// <returns>IEnumerable{BaseItem}.</returns> + IEnumerable<BaseItem> ReplaceVideosWithPrimaryVersions(IEnumerable<BaseItem> items); } public static class LibraryManagerExtensions diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 4a96c580c..2b32dc1d8 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -137,6 +137,9 @@ <Compile Include="..\MediaBrowser.Model\Dto\ItemIndex.cs"> <Link>Dto\ItemIndex.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Dto\MediaVersionInfo.cs"> + <Link>Dto\MediaVersionInfo.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Dto\RecommendationDto.cs"> <Link>Dto\RecommendationDto.cs</Link> </Compile> diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 958a4a726..baf1fc451 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -124,6 +124,9 @@ <Compile Include="..\MediaBrowser.Model\Dto\ItemIndex.cs"> <Link>Dto\ItemIndex.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Dto\MediaVersionInfo.cs"> + <Link>Dto\MediaVersionInfo.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Dto\RecommendationDto.cs"> <Link>Dto\RecommendationDto.cs</Link> </Compile> diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 857332b06..451afee6b 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -495,7 +495,6 @@ namespace MediaBrowser.Model.Dto /// <value>The part count.</value> public int? PartCount { get; set; } public int? AlternateVersionCount { get; set; } - public string PrimaryVersionId { get; set; } /// <summary> /// Determines whether the specified type is type. diff --git a/MediaBrowser.Model/Dto/MediaVersionInfo.cs b/MediaBrowser.Model/Dto/MediaVersionInfo.cs new file mode 100644 index 000000000..809a1e3d9 --- /dev/null +++ b/MediaBrowser.Model/Dto/MediaVersionInfo.cs @@ -0,0 +1,30 @@ +using MediaBrowser.Model.Entities; +using System.Collections.Generic; + +namespace MediaBrowser.Model.Dto +{ + public class MediaVersionInfo + { + public string Id { get; set; } + + public string Path { get; set; } + + public LocationType LocationType { get; set; } + + public string Name { get; set; } + + public long? RunTimeTicks { get; set; } + + public VideoType? VideoType { get; set; } + + public IsoType? IsoType { get; set; } + + public Video3DFormat? Video3DFormat { get; set; } + + public List<MediaStream> MediaStreams { get; set; } + + public List<ChapterInfoDto> Chapters { get; set; } + + public bool? IsHD { get; set; } + } +} diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index cce3e74cc..12a462589 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -76,6 +76,7 @@ <Compile Include="Dto\ItemCounts.cs" /> <Compile Include="Dto\ItemIndex.cs" /> <Compile Include="Dto\RecommendationDto.cs" /> + <Compile Include="Dto\MediaVersionInfo.cs" /> <Compile Include="Entities\PackageReviewInfo.cs" /> <Compile Include="FileOrganization\FileOrganizationResult.cs" /> <Compile Include="FileOrganization\FileOrganizationQuery.cs" /> diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index 22b7e7054..ae5bf7716 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -208,8 +208,8 @@ namespace MediaBrowser.Server.Implementations.Channels var query = new InternalChannelItemQuery { - User = user, - CategoryId = categoryId + User = user, + CategoryId = categoryId }; var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false); @@ -236,7 +236,7 @@ namespace MediaBrowser.Server.Implementations.Channels var tasks = items.Select(GetChannelItemEntity); var returnItems = await Task.WhenAll(tasks).ConfigureAwait(false); - + returnItems = new BaseItem[] {}; var returnItemArray = returnItems.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .ToArray(); @@ -251,19 +251,25 @@ namespace MediaBrowser.Server.Implementations.Channels { BaseItem item; + Guid id; + if (info.Type == ChannelItemType.Category) { + id = info.Id.GetMBId(typeof(ChannelCategoryItem)); item = new ChannelCategoryItem(); } else if (info.MediaType == ChannelMediaType.Audio) { + id = info.Id.GetMBId(typeof(ChannelCategoryItem)); item = new ChannelAudioItem(); } else { + id = info.Id.GetMBId(typeof(ChannelVideoItem)); item = new ChannelVideoItem(); } + item.Id = id; item.Name = info.Name; item.Genres = info.Genres; item.CommunityRating = info.CommunityRating; diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 19d834c20..a66cb148f 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -651,7 +651,7 @@ namespace MediaBrowser.Server.Implementations.Dto /// <param name="chapterInfo">The chapter info.</param> /// <param name="item">The item.</param> /// <returns>ChapterInfoDto.</returns> - private ChapterInfoDto GetChapterInfoDto(ChapterInfo chapterInfo, BaseItem item) + public ChapterInfoDto GetChapterInfoDto(ChapterInfo chapterInfo, BaseItem item) { var dto = new ChapterInfoDto { @@ -1084,11 +1084,6 @@ namespace MediaBrowser.Server.Implementations.Dto dto.PartCount = video.AdditionalPartIds.Count + 1; dto.AlternateVersionCount = video.AlternateVersionCount; - if (video.PrimaryVersionId.HasValue) - { - dto.PrimaryVersionId = video.PrimaryVersionId.Value.ToString("N"); - } - if (fields.Contains(ItemFields.Chapters)) { dto.Chapters = _itemRepo.GetChapters(video.Id).Select(c => GetChapterInfoDto(c, item)).ToList(); diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 0b1947d4c..91abb6b4f 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -26,6 +26,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MoreLinq; using SortOrder = MediaBrowser.Model.Entities.SortOrder; namespace MediaBrowser.Server.Implementations.Library @@ -540,6 +541,29 @@ namespace MediaBrowser.Server.Implementations.Library return item; } + public IEnumerable<BaseItem> ReplaceVideosWithPrimaryVersions(IEnumerable<BaseItem> items) + { + return items.Select(i => + { + var video = i as Video; + + if (video != null) + { + if (video.PrimaryVersionId.HasValue) + { + var primary = GetItemById(video.PrimaryVersionId.Value) as Video; + + if (primary != null) + { + return primary; + } + } + } + + return i; + + }).DistinctBy(i => i.Id); + } /// <summary> /// Ensure supplied item has only one instance throughout diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index aaafd35a9..f48a4430f 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -35,6 +35,8 @@ namespace MediaBrowser.Server.Implementations.Library var inputItems = user.RootFolder.GetRecursiveChildren(user, null).Where(i => !(i is ICollectionFolder)); + inputItems = _libraryManager.ReplaceVideosWithPrimaryVersions(inputItems); + var results = await GetSearchHints(inputItems, query).ConfigureAwait(false); // Include item types diff --git a/MediaBrowser.ServerApplication/LibraryViewer.cs b/MediaBrowser.ServerApplication/LibraryViewer.cs index a8eda801b..6c40b549b 100644 --- a/MediaBrowser.ServerApplication/LibraryViewer.cs +++ b/MediaBrowser.ServerApplication/LibraryViewer.cs @@ -119,11 +119,9 @@ namespace MediaBrowser.ServerApplication var subFolder = item as Folder; if (subFolder != null) { - var prefs = _displayPreferencesManager.GetDisplayPreferences(subFolder.DisplayPreferencesId, user.Id, "LibraryExplorer"); - var subChildren = isPhysical ? subFolder.Children : subFolder.GetChildren(_currentUser, true); - AddChildren(node, OrderBy(subChildren, user, prefs.SortBy), user, isPhysical); + AddChildren(node, OrderBy(subChildren, user, ItemSortBy.SortName), user, isPhysical); node.Text = item.Name + " (" + node.Nodes.Count + ")"; } else |
