VideosService.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. using MediaBrowser.Common.IO;
  2. using MediaBrowser.Controller.Configuration;
  3. using MediaBrowser.Controller.Dto;
  4. using MediaBrowser.Controller.Entities;
  5. using MediaBrowser.Controller.Library;
  6. using MediaBrowser.Controller.Persistence;
  7. using MediaBrowser.Model.Querying;
  8. using ServiceStack;
  9. using System;
  10. using System.Linq;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. namespace MediaBrowser.Api
  14. {
  15. [Route("/Videos/{Id}/AdditionalParts", "GET")]
  16. [Api(Description = "Gets additional parts for a video.")]
  17. public class GetAdditionalParts : IReturn<ItemsResult>
  18. {
  19. [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
  20. public Guid? UserId { get; set; }
  21. /// <summary>
  22. /// Gets or sets the id.
  23. /// </summary>
  24. /// <value>The id.</value>
  25. [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
  26. public string Id { get; set; }
  27. }
  28. [Route("/Videos/{Id}/AlternateVersions", "DELETE")]
  29. [Api(Description = "Assigns videos as alternates of antoher.")]
  30. public class DeleteAlternateVersions : IReturnVoid
  31. {
  32. [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
  33. public string Id { get; set; }
  34. }
  35. [Route("/Videos/MergeVersions", "POST")]
  36. [Api(Description = "Merges videos into a single record")]
  37. public class MergeVersions : IReturnVoid
  38. {
  39. [ApiMember(Name = "Ids", Description = "Item id list. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
  40. public string Ids { get; set; }
  41. }
  42. public class VideosService : BaseApiService
  43. {
  44. private readonly ILibraryManager _libraryManager;
  45. private readonly IUserManager _userManager;
  46. private readonly IDtoService _dtoService;
  47. private readonly IFileSystem _fileSystem;
  48. private readonly IItemRepository _itemRepo;
  49. private readonly IServerConfigurationManager _config;
  50. public VideosService(ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService, IItemRepository itemRepo, IFileSystem fileSystem, IServerConfigurationManager config)
  51. {
  52. _libraryManager = libraryManager;
  53. _userManager = userManager;
  54. _dtoService = dtoService;
  55. _itemRepo = itemRepo;
  56. _fileSystem = fileSystem;
  57. _config = config;
  58. }
  59. /// <summary>
  60. /// Gets the specified request.
  61. /// </summary>
  62. /// <param name="request">The request.</param>
  63. /// <returns>System.Object.</returns>
  64. public object Get(GetAdditionalParts request)
  65. {
  66. var user = request.UserId.HasValue ? _userManager.GetUserById(request.UserId.Value) : null;
  67. var item = string.IsNullOrEmpty(request.Id)
  68. ? (request.UserId.HasValue
  69. ? user.RootFolder
  70. : _libraryManager.RootFolder)
  71. : _dtoService.GetItemByDtoId(request.Id, request.UserId);
  72. // Get everything
  73. var fields = Enum.GetNames(typeof(ItemFields))
  74. .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
  75. .ToList();
  76. var video = (Video)item;
  77. var items = video.GetAdditionalParts()
  78. .Select(i => _dtoService.GetBaseItemDto(i, fields, user, video))
  79. .ToArray();
  80. var result = new ItemsResult
  81. {
  82. Items = items,
  83. TotalRecordCount = items.Length
  84. };
  85. return ToOptimizedSerializedResultUsingCache(result);
  86. }
  87. public void Delete(DeleteAlternateVersions request)
  88. {
  89. var task = RemoveAlternateVersions(request);
  90. Task.WaitAll(task);
  91. }
  92. private async Task RemoveAlternateVersions(DeleteAlternateVersions request)
  93. {
  94. var video = (Video)_dtoService.GetItemByDtoId(request.Id);
  95. foreach (var link in video.GetLinkedAlternateVersions())
  96. {
  97. link.PrimaryVersionId = null;
  98. await link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
  99. }
  100. video.LinkedAlternateVersions.Clear();
  101. await video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
  102. }
  103. public void Post(MergeVersions request)
  104. {
  105. var task = MergeVersions(request);
  106. Task.WaitAll(task);
  107. }
  108. private async Task MergeVersions(MergeVersions request)
  109. {
  110. var items = request.Ids.Split(',')
  111. .Select(i => new Guid(i))
  112. .Select(i => _libraryManager.GetItemById(i))
  113. .ToList();
  114. if (items.Count < 2)
  115. {
  116. throw new ArgumentException("Please supply at least two videos to merge.");
  117. }
  118. if (items.Any(i => !(i is Video)))
  119. {
  120. throw new ArgumentException("Only videos can be grouped together.");
  121. }
  122. var videos = items.Cast<Video>().ToList();
  123. var videosWithVersions = videos.Where(i => i.AlternateVersionCount > 0)
  124. .ToList();
  125. if (videosWithVersions.Count > 1)
  126. {
  127. throw new ArgumentException("Videos with sub-versions cannot be merged.");
  128. }
  129. var primaryVersion = videosWithVersions.FirstOrDefault();
  130. if (primaryVersion == null)
  131. {
  132. primaryVersion = videos.OrderByDescending(i =>
  133. {
  134. var stream = i.GetDefaultVideoStream();
  135. return stream == null || stream.Width == null ? 0 : stream.Width.Value;
  136. }).ThenBy(i => i.Name.Length)
  137. .First();
  138. }
  139. foreach (var item in videos.Where(i => i.Id != primaryVersion.Id))
  140. {
  141. item.PrimaryVersionId = primaryVersion.Id;
  142. await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
  143. primaryVersion.LinkedAlternateVersions.Add(new LinkedChild
  144. {
  145. Path = item.Path,
  146. ItemId = item.Id
  147. });
  148. }
  149. await primaryVersion.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
  150. }
  151. }
  152. }