using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Entities; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api.Controllers { /// /// The instant mix controller. /// [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class InstantMixController : BaseJellyfinApiController { private readonly IUserManager _userManager; private readonly IDtoService _dtoService; private readonly ILibraryManager _libraryManager; private readonly IMusicManager _musicManager; /// /// Initializes a new instance of the class. /// /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. public InstantMixController( IUserManager userManager, IDtoService dtoService, IMusicManager musicManager, ILibraryManager libraryManager) { _userManager = userManager; _dtoService = dtoService; _musicManager = musicManager; _libraryManager = libraryManager; } /// /// Creates an instant playlist based on a given song. /// /// The item id. /// Optional. Filter by user id, and attach user data. /// Optional. The maximum number of records to return. /// Optional. Specify additional fields of information to return in the output. /// Optional. Include image information in output. /// Optional. Include user data. /// Optional. The max number of images to return, per image type. /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. [HttpGet("Songs/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromSong( [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, [FromQuery] bool? enableImages, [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) { var item = _libraryManager.GetItemById(id); var user = userId is null || userId.Value.Equals(default) ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } /// /// Creates an instant playlist based on a given album. /// /// The item id. /// Optional. Filter by user id, and attach user data. /// Optional. The maximum number of records to return. /// Optional. Specify additional fields of information to return in the output. /// Optional. Include image information in output. /// Optional. Include user data. /// Optional. The max number of images to return, per image type. /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. [HttpGet("Albums/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromAlbum( [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, [FromQuery] bool? enableImages, [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) { var album = _libraryManager.GetItemById(id); var user = userId is null || userId.Value.Equals(default) ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(album, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } /// /// Creates an instant playlist based on a given playlist. /// /// The item id. /// Optional. Filter by user id, and attach user data. /// Optional. The maximum number of records to return. /// Optional. Specify additional fields of information to return in the output. /// Optional. Include image information in output. /// Optional. Include user data. /// Optional. The max number of images to return, per image type. /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. [HttpGet("Playlists/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromPlaylist( [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, [FromQuery] bool? enableImages, [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) { var playlist = (Playlist)_libraryManager.GetItemById(id); var user = userId is null || userId.Value.Equals(default) ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(playlist, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } /// /// Creates an instant playlist based on a given genre. /// /// The genre name. /// Optional. Filter by user id, and attach user data. /// Optional. The maximum number of records to return. /// Optional. Specify additional fields of information to return in the output. /// Optional. Include image information in output. /// Optional. Include user data. /// Optional. The max number of images to return, per image type. /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. [HttpGet("MusicGenres/{name}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromMusicGenreByName( [FromRoute, Required] string name, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, [FromQuery] bool? enableImages, [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) { var user = userId is null || userId.Value.Equals(default) ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromGenres(new[] { name }, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } /// /// Creates an instant playlist based on a given artist. /// /// The item id. /// Optional. Filter by user id, and attach user data. /// Optional. The maximum number of records to return. /// Optional. Specify additional fields of information to return in the output. /// Optional. Include image information in output. /// Optional. Include user data. /// Optional. The max number of images to return, per image type. /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. [HttpGet("Artists/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromArtists( [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, [FromQuery] bool? enableImages, [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) { var item = _libraryManager.GetItemById(id); var user = userId is null || userId.Value.Equals(default) ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } /// /// Creates an instant playlist based on a given item. /// /// The item id. /// Optional. Filter by user id, and attach user data. /// Optional. The maximum number of records to return. /// Optional. Specify additional fields of information to return in the output. /// Optional. Include image information in output. /// Optional. Include user data. /// Optional. The max number of images to return, per image type. /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. [HttpGet("Items/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromItem( [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, [FromQuery] bool? enableImages, [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) { var item = _libraryManager.GetItemById(id); var user = userId is null || userId.Value.Equals(default) ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } /// /// Creates an instant playlist based on a given artist. /// /// The item id. /// Optional. Filter by user id, and attach user data. /// Optional. The maximum number of records to return. /// Optional. Specify additional fields of information to return in the output. /// Optional. Include image information in output. /// Optional. Include user data. /// Optional. The max number of images to return, per image type. /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. [HttpGet("Artists/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] [Obsolete("Use GetInstantMixFromArtists")] public ActionResult> GetInstantMixFromArtists2( [FromQuery, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, [FromQuery] bool? enableImages, [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) { return GetInstantMixFromArtists( id, userId, limit, fields, enableImages, enableUserData, imageTypeLimit, enableImageTypes); } /// /// Creates an instant playlist based on a given genre. /// /// The item id. /// Optional. Filter by user id, and attach user data. /// Optional. The maximum number of records to return. /// Optional. Specify additional fields of information to return in the output. /// Optional. Include image information in output. /// Optional. Include user data. /// Optional. The max number of images to return, per image type. /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. [HttpGet("MusicGenres/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromMusicGenreById( [FromQuery, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, [FromQuery] bool? enableImages, [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) { var item = _libraryManager.GetItemById(id); var user = userId is null || userId.Value.Equals(default) ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } private QueryResult GetResult(List items, User? user, int? limit, DtoOptions dtoOptions) { var list = items; var totalCount = list.Count; if (limit.HasValue && limit < list.Count) { list = list.GetRange(0, limit.Value); } var returnList = _dtoService.GetBaseItemDtos(list, dtoOptions, user); var result = new QueryResult( 0, totalCount, returnList); return result; } } }