diff options
17 files changed, 239 insertions, 24 deletions
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index bcc487a5d..85e40eda1 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -66,7 +66,7 @@ <Compile Include="..\SharedVersion.cs"> <Link>Properties\SharedVersion.cs</Link> </Compile> - <Compile Include="AlbumsService.cs" /> + <Compile Include="Music\AlbumsService.cs" /> <Compile Include="AppThemeService.cs" /> <Compile Include="BaseApiService.cs" /> <Compile Include="ConfigurationService.cs" /> @@ -81,7 +81,7 @@ <Compile Include="Images\ImageRequest.cs" /> <Compile Include="Images\ImageService.cs" /> <Compile Include="Images\ImageWriter.cs" /> - <Compile Include="InstantMixService.cs" /> + <Compile Include="Music\InstantMixService.cs" /> <Compile Include="ItemLookupService.cs" /> <Compile Include="ItemRefreshService.cs" /> <Compile Include="ItemUpdateService.cs" /> diff --git a/MediaBrowser.Api/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs index 5787ad180..a80dd796a 100644 --- a/MediaBrowser.Api/AlbumsService.cs +++ b/MediaBrowser.Api/Music/AlbumsService.cs @@ -8,7 +8,7 @@ using System; using System.Collections.Generic; using System.Linq; -namespace MediaBrowser.Api +namespace MediaBrowser.Api.Music { [Route("/Albums/{Id}/Similar", "GET")] [Api(Description = "Finds albums similar to a given album.")] diff --git a/MediaBrowser.Api/InstantMixService.cs b/MediaBrowser.Api/Music/InstantMixService.cs index 624137677..a8446a7ef 100644 --- a/MediaBrowser.Api/InstantMixService.cs +++ b/MediaBrowser.Api/Music/InstantMixService.cs @@ -7,7 +7,7 @@ using System; using System.Collections.Generic; using System.Linq; -namespace MediaBrowser.Api +namespace MediaBrowser.Api.Music { [Route("/Songs/{Id}/InstantMix", "GET")] [Api(Description = "Creates an instant playlist based on a given song")] diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 629f9b233..198e1c383 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Api /// Class GetNextUpEpisodes /// </summary> [Route("/Shows/NextUp", "GET")] - [Api(("Gets a list of currently installed plugins"))] + [Api(("Gets a list of next up episodes"))] public class GetNextUpEpisodes : IReturn<ItemsResult>, IHasItemFields { /// <summary> @@ -53,6 +53,39 @@ namespace MediaBrowser.Api public string SeriesId { get; set; } } + [Route("/Shows/Upcoming", "GET")] + [Api(("Gets a list of upcoming episodes"))] + public class GetUpcomingEpisodes : IReturn<ItemsResult>, IHasItemFields + { + /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid UserId { get; set; } + + /// <summary> + /// Skips over a given number of items within the results. Use for paging. + /// </summary> + /// <value>The start index.</value> + [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? StartIndex { get; set; } + + /// <summary> + /// The maximum number of items to return + /// </summary> + /// <value>The limit.</value> + [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? Limit { get; set; } + + /// <summary> + /// Fields to return within the items, in addition to basic information + /// </summary> + /// <value>The fields.</value> + [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] + public string Fields { get; set; } + } + [Route("/Shows/{Id}/Similar", "GET")] [Api(Description = "Finds tv shows similar to a given one.")] public class GetSimilarShows : BaseGetSimilarItemsFromItem @@ -85,7 +118,7 @@ namespace MediaBrowser.Api [ApiMember(Name = "SeasonId", Description = "Optional. Filter by season id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string SeasonId { get; set; } - + [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? IsMissing { get; set; } @@ -186,6 +219,39 @@ namespace MediaBrowser.Api return ToOptimizedSerializedResultUsingCache(result); } + public object Get(GetUpcomingEpisodes request) + { + var user = _userManager.GetUserById(request.UserId); + + var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager) + .OfType<Episode>(); + + var itemsList = _libraryManager.Sort(items, user, new[] { "PremiereDate", "AirTime", "SortName" }, SortOrder.Ascending) + .Cast<Episode>() + .ToList(); + + var unairedEpisodes = itemsList.Where(i => i.IsUnaired).ToList(); + + var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime(); + var previousEpisodes = itemsList.Where(i => !i.IsUnaired && (i.PremiereDate ?? DateTime.MinValue) >= minPremiereDate).ToList(); + + previousEpisodes.AddRange(unairedEpisodes); + + var pagedItems = ApplyPaging(previousEpisodes, request.StartIndex, request.Limit); + + var fields = request.GetItemFields().ToList(); + + var returnItems = pagedItems.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray(); + + var result = new ItemsResult + { + TotalRecordCount = itemsList.Count, + Items = returnItems + }; + + return ToOptimizedSerializedResultUsingCache(result); + } + /// <summary> /// Gets the specified request. /// </summary> @@ -198,7 +264,7 @@ namespace MediaBrowser.Api var itemsList = GetNextUpEpisodes(request) .ToList(); - var pagedItems = ApplyPaging(request, itemsList); + var pagedItems = ApplyPaging(itemsList, request.StartIndex, request.Limit); var fields = request.GetItemFields().ToList(); @@ -321,21 +387,22 @@ namespace MediaBrowser.Api /// <summary> /// Applies the paging. /// </summary> - /// <param name="request">The request.</param> /// <param name="items">The items.</param> + /// <param name="startIndex">The start index.</param> + /// <param name="limit">The limit.</param> /// <returns>IEnumerable{BaseItem}.</returns> - private IEnumerable<BaseItem> ApplyPaging(GetNextUpEpisodes request, IEnumerable<BaseItem> items) + private IEnumerable<BaseItem> ApplyPaging(IEnumerable<BaseItem> items, int? startIndex, int? limit) { // Start at - if (request.StartIndex.HasValue) + if (startIndex.HasValue) { - items = items.Skip(request.StartIndex.Value); + items = items.Skip(startIndex.Value); } // Return limit - if (request.Limit.HasValue) + if (limit.HasValue) { - items = items.Take(request.Limit.Value); + items = items.Take(limit.Value); } return items; @@ -409,7 +476,7 @@ namespace MediaBrowser.Api return items; } - + public object Get(GetEpisodes request) { var user = _userManager.GetUserById(request.UserId); @@ -435,7 +502,7 @@ namespace MediaBrowser.Api { throw new ResourceNotFoundException("No season exists with Id " + request.SeasonId); } - + episodes = season.GetEpisodes(user); } diff --git a/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs b/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs new file mode 100644 index 000000000..d26bf5b35 --- /dev/null +++ b/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs @@ -0,0 +1,13 @@ +using System; + +namespace MediaBrowser.Controller.Collections +{ + public class CollectionCreationOptions + { + public string Name { get; set; } + + public Guid ParentId { get; set; } + + public bool IsLocked { get; set; } + } +} diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs new file mode 100644 index 000000000..a1e6b2c12 --- /dev/null +++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs @@ -0,0 +1,31 @@ +using System; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Collections +{ + public interface ICollectionManager + { + /// <summary> + /// Creates the collection. + /// </summary> + /// <param name="options">The options.</param> + /// <returns>Task.</returns> + Task CreateCollection(CollectionCreationOptions options); + + /// <summary> + /// Adds to collection. + /// </summary> + /// <param name="collectionId">The collection identifier.</param> + /// <param name="itemId">The item identifier.</param> + /// <returns>Task.</returns> + Task AddToCollection(Guid collectionId, Guid itemId); + + /// <summary> + /// Removes from collection. + /// </summary> + /// <param name="collectionId">The collection identifier.</param> + /// <param name="itemId">The item identifier.</param> + /// <returns>Task.</returns> + Task RemoveFromCollection(Guid collectionId, Guid itemId); + } +} diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index 1829e10c7..0290fa39a 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Providers; +using System; using System.Collections.Generic; using System.Linq; @@ -23,7 +24,7 @@ namespace MediaBrowser.Controller.Entities { var hasChanges = base.BeforeMetadataRefresh(); - if (string.Equals("default", Name, System.StringComparison.OrdinalIgnoreCase)) + if (string.Equals("default", Name, StringComparison.OrdinalIgnoreCase)) { Name = "Media Folders"; hasChanges = true; diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index ff446f2ef..100ac9f4c 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -68,6 +68,8 @@ <Compile Include="..\SharedVersion.cs"> <Link>Properties\SharedVersion.cs</Link> </Compile> + <Compile Include="Collections\CollectionCreationOptions.cs" /> + <Compile Include="Collections\ICollectionManager.cs" /> <Compile Include="Drawing\IImageProcessor.cs" /> <Compile Include="Drawing\ImageFormat.cs" /> <Compile Include="Drawing\ImageProcessingOptions.cs" /> diff --git a/MediaBrowser.Providers/Music/MusicExternalIds.cs b/MediaBrowser.Providers/Music/MusicExternalIds.cs index a25ab9deb..a4eab1eee 100644 --- a/MediaBrowser.Providers/Music/MusicExternalIds.cs +++ b/MediaBrowser.Providers/Music/MusicExternalIds.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.Music public bool Supports(IHasProviderIds item) { - return item is Audio || item is MusicAlbum || item is MusicArtist; + return item is Audio || item is MusicAlbum; } } diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs new file mode 100644 index 000000000..da444d100 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs @@ -0,0 +1,79 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Collections; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Collections +{ + public class CollectionManager : ICollectionManager + { + private readonly ILibraryManager _libraryManager; + private readonly IFileSystem _fileSystem; + private readonly ILibraryMonitor _iLibraryMonitor; + + public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor) + { + _libraryManager = libraryManager; + _fileSystem = fileSystem; + _iLibraryMonitor = iLibraryMonitor; + } + + public async Task CreateCollection(CollectionCreationOptions options) + { + var name = options.Name; + + var folderName = _fileSystem.GetValidFilename(name); + + var parentFolder = _libraryManager.GetItemById(options.ParentId) as Folder; + + if (parentFolder == null) + { + throw new ArgumentException(); + } + + var path = Path.Combine(parentFolder.Path, folderName); + + _iLibraryMonitor.ReportFileSystemChangeBeginning(path); + + try + { + Directory.CreateDirectory(path); + + var collection = new BoxSet + { + Name = name, + Parent = parentFolder, + DisplayMediaType = "Collection", + Path = path, + DontFetchMeta = options.IsLocked + }; + + await parentFolder.AddChild(collection, CancellationToken.None).ConfigureAwait(false); + + await collection.RefreshMetadata(new MetadataRefreshOptions(), CancellationToken.None) + .ConfigureAwait(false); + } + finally + { + // Refresh handled internally + _iLibraryMonitor.ReportFileSystemChangeComplete(path, false); + } + } + + public Task AddToCollection(Guid collectionId, Guid itemId) + { + throw new NotImplementedException(); + } + + public Task RemoveFromCollection(Guid collectionId, Guid itemId) + { + throw new NotImplementedException(); + } + } +} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index c0d784fcc..ad2852a91 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -3,6 +3,8 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; using Mono.Nat; +using Mono.Nat.Enums; +using Mono.Nat.EventArgs; using System; using System.IO; using System.Text; diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index 871171541..ac1927931 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -48,7 +48,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio var collectionType = args.GetCollectionType(); - // If there's a collection type and it's not music, it can't be a series + // If there's a collection type and it's not music, don't allow it. if (!string.IsNullOrEmpty(collectionType) && !string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs index 9a1373460..83d8e4b73 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs @@ -105,7 +105,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) { - return !item.HasImage(ImageType.Primary) && (DateTime.UtcNow - date).TotalDays >= 1; + var liveTvItem = item as LiveTvChannel; + + if (liveTvItem != null) + { + return !liveTvItem.HasImage(ImageType.Primary) && (liveTvItem.HasProviderImage ?? true) && (DateTime.UtcNow - date).TotalHours >= 6; + } + return false; } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs index cb7635b45..081722bb2 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs @@ -105,7 +105,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) { - return !item.HasImage(ImageType.Primary) && (DateTime.UtcNow - date).TotalHours >= 6; + var liveTvItem = item as LiveTvProgram; + + if (liveTvItem != null) + { + return !liveTvItem.HasImage(ImageType.Primary) && (liveTvItem.HasProviderImage ?? true) && (DateTime.UtcNow - date).TotalHours >= 6; + } + return false; } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs index be8955d16..7aa5dcebd 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs @@ -105,7 +105,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) { - return !item.HasImage(ImageType.Primary) && (DateTime.UtcNow - date).TotalHours >= 3; + var liveTvItem = item as ILiveTvRecording; + + if (liveTvItem != null) + { + return !liveTvItem.HasImage(ImageType.Primary) && (liveTvItem.RecordingInfo.HasImage ?? true) && (DateTime.UtcNow - date).TotalHours >= 6; + } + return false; } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index f0b08b923..0165cefad 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -56,8 +56,9 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath> </Reference> - <Reference Include="Mono.Nat"> - <HintPath>..\packages\Mono.Nat.1.1.13\lib\Net40\Mono.Nat.dll</HintPath> + <Reference Include="Mono.Nat, Version=1.2.3.0, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\packages\Mono.Nat.1.2.3\lib\Net40\Mono.Nat.dll</HintPath> </Reference> <Reference Include="ServiceStack.Api.Swagger"> <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath> @@ -108,6 +109,7 @@ <Link>Properties\SharedVersion.cs</Link> </Compile> <Compile Include="BdInfo\BdInfoExaminer.cs" /> + <Compile Include="Collections\CollectionManager.cs" /> <Compile Include="Configuration\ServerConfigurationManager.cs" /> <Compile Include="Drawing\ImageHeader.cs" /> <Compile Include="Drawing\PercentPlayedDrawer.cs" /> diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 258e0639d..3c984e265 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -2,7 +2,7 @@ <packages>
<package id="Alchemy" version="2.2.1" targetFramework="net45" />
<package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
- <package id="Mono.Nat" version="1.1.13" targetFramework="net45" />
+ <package id="Mono.Nat" version="1.2.3" targetFramework="net45" />
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
<package id="System.Data.SQLite.x86" version="1.0.90.0" targetFramework="net45" />
</packages>
\ No newline at end of file |
