diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs index 31fda199e5..af200895eb 100644 --- a/MediaBrowser.Api/VideosService.cs +++ b/MediaBrowser.Api/VideosService.cs @@ -1,4 +1,7 @@ -using MediaBrowser.Controller.Dto; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Querying; @@ -37,14 +40,44 @@ namespace MediaBrowser.Api [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; } + + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/Videos/{Id}/AlternateVersions", "DELETE")] + [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; } + + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + public class VideosService : BaseApiService { private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDtoService _dtoService; - public VideosService( ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService) + public VideosService(ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService) { _libraryManager = libraryManager; _userManager = userManager; @@ -115,5 +148,61 @@ namespace MediaBrowser.Api return ToOptimizedSerializedResultUsingCache(result); } + + public void Post(PostAlternateVersions request) + { + var task = AddAlternateVersions(request); + + Task.WaitAll(task); + } + + public void Delete(DeleteAlternateVersions request) + { + var task = RemoveAlternateVersions(request); + + Task.WaitAll(task); + } + + private async Task AddAlternateVersions(PostAlternateVersions request) + { + var video = (Video)_dtoService.GetItemByDtoId(request.Id); + + var list = new List(); + var currentAlternateVersions = video.GetAlternateVersions().ToList(); + + foreach (var itemId in request.AlternateVersionIds.Split(',').Select(i => new Guid(i))) + { + var item = _libraryManager.GetItemById(itemId) as Video; + + if (item == null) + { + throw new ArgumentException("No item exists with the supplied Id"); + } + + if (currentAlternateVersions.Any(i => i.Id == itemId)) + { + throw new ArgumentException("Item already exists."); + } + + list.Add(new LinkedChild + { + Path = item.Path, + Type = LinkedChildType.Manual + }); + + item.PrimaryVersionId = video.Id; + } + + video.LinkedAlternateVersions.AddRange(list); + + await video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + + await video.RefreshMetadata(CancellationToken.None).ConfigureAwait(false); + } + + private async Task RemoveAlternateVersions(DeleteAlternateVersions request) + { + var video = (Video)_dtoService.GetItemByDtoId(request.Id); + } } } diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index e30458dd8f..18db21f382 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; @@ -20,26 +21,27 @@ namespace MediaBrowser.Controller.Entities { public bool IsMultiPart { get; set; } public bool HasLocalAlternateVersions { get; set; } + public Guid? PrimaryVersionId { get; set; } public List AdditionalPartIds { get; set; } - public List AlternateVersionIds { get; set; } + public List LocalAlternateVersionIds { get; set; } public Video() { PlayableStreamFileNames = new List(); AdditionalPartIds = new List(); - AlternateVersionIds = new List(); + LocalAlternateVersionIds = new List(); Tags = new List(); SubtitleFiles = new List(); LinkedAlternateVersions = new List(); } [IgnoreDataMember] - public bool HasAlternateVersions + public int AlternateVersionCount { get { - return HasLocalAlternateVersions || LinkedAlternateVersions.Count > 0; + return LinkedAlternateVersions.Count + LocalAlternateVersionIds.Count; } } @@ -51,7 +53,7 @@ namespace MediaBrowser.Controller.Entities /// IEnumerable{BaseItem}. public IEnumerable GetAlternateVersions() { - var filesWithinSameDirectory = AlternateVersionIds + var filesWithinSameDirectory = LocalAlternateVersionIds .Select(i => LibraryManager.GetItemById(i)) .Where(i => i != null) .OfType