From b3127f19b546f3edce959dd70cafffb3d422a673 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 27 Jan 2015 01:50:40 -0500 Subject: updated tvdb search --- MediaBrowser.Controller/Entities/CollectionFolder.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.Controller/Entities/CollectionFolder.cs') diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index f47a439a7..5452c63a4 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -121,12 +121,6 @@ namespace MediaBrowser.Controller.Entities return args; } - // Cache this since it will be used a lot - /// - /// The null task result - /// - private static readonly Task NullTaskResult = Task.FromResult(null); - /// /// Compare our current children (presumably just read from the repo) with the current state of the file system and adjust for any changes /// ***Currently does not contain logic to maintain items that are unavailable in the file system*** @@ -138,7 +132,7 @@ namespace MediaBrowser.Controller.Entities /// The refresh options. /// The directory service. /// Task. - protected override async Task ValidateChildrenInternal(IProgress progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) + protected override Task ValidateChildrenInternal(IProgress progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) { var list = PhysicalLocationsList.ToList(); @@ -146,8 +140,10 @@ namespace MediaBrowser.Controller.Entities if (!list.SequenceEqual(PhysicalLocationsList)) { - await UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); + return UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken); } + + return Task.FromResult(true); } /// -- cgit v1.2.3 From 782fe92cf766c09c84200e9e2228e555e6644add Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 27 Jan 2015 17:45:59 -0500 Subject: support artists tag value --- MediaBrowser.Api/SearchService.cs | 13 ++----- MediaBrowser.Api/VideosService.cs | 1 - .../Entities/AggregateFolder.cs | 2 +- .../Entities/Audio/MusicAlbum.cs | 6 ---- .../Entities/CollectionFolder.cs | 2 +- MediaBrowser.Controller/Entities/User.cs | 2 +- MediaBrowser.Controller/Library/ItemResolveArgs.cs | 18 ++-------- MediaBrowser.Model/Entities/MetadataProviders.cs | 3 +- MediaBrowser.Model/Sync/SyncJobCreationResult.cs | 9 ++++- MediaBrowser.Providers/Manager/ImageSaver.cs | 3 +- .../MediaInfo/FFProbeAudioInfo.cs | 40 +++++++++++++++++----- MediaBrowser.Providers/Music/MusicExternalIds.cs | 23 +++++++++++++ .../Library/LibraryManager.cs | 11 +++--- .../Library/Resolvers/SpecialFolderResolver.cs | 7 ++-- .../Sorting/AiredEpisodeOrderComparer.cs | 2 ++ .../Sync/SyncManager.cs | 9 ++++- 16 files changed, 94 insertions(+), 57 deletions(-) (limited to 'MediaBrowser.Controller/Entities/CollectionFolder.cs') diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs index 4dcf72407..ee48946d5 100644 --- a/MediaBrowser.Api/SearchService.cs +++ b/MediaBrowser.Api/SearchService.cs @@ -208,17 +208,10 @@ namespace MediaBrowser.Api if (album != null) { - var songs = album.GetRecursiveChildren(i => i is Audio) - .Cast private readonly IServerApplicationPaths _appPaths; - private readonly ILibraryManager _libraryManager; public IDirectoryService DirectoryService { get; private set; } @@ -25,11 +24,10 @@ namespace MediaBrowser.Controller.Library /// Initializes a new instance of the class. /// /// The app paths. - /// The library manager. - public ItemResolveArgs(IServerApplicationPaths appPaths, ILibraryManager libraryManager, IDirectoryService directoryService) + /// The directory service. + public ItemResolveArgs(IServerApplicationPaths appPaths, IDirectoryService directoryService) { _appPaths = appPaths; - _libraryManager = libraryManager; DirectoryService = directoryService; } @@ -136,18 +134,6 @@ namespace MediaBrowser.Controller.Library } } - /// - /// Gets a value indicating whether this instance is root. - /// - /// true if this instance is root; otherwise, false. - public bool IsRoot - { - get - { - return Parent == null; - } - } - /// /// Gets or sets the additional locations. /// diff --git a/MediaBrowser.Model/Entities/MetadataProviders.cs b/MediaBrowser.Model/Entities/MetadataProviders.cs index e86773789..7644b150a 100644 --- a/MediaBrowser.Model/Entities/MetadataProviders.cs +++ b/MediaBrowser.Model/Entities/MetadataProviders.cs @@ -40,6 +40,7 @@ namespace MediaBrowser.Model.Entities NesBoxRom = 14, TvRage = 15, AudioDbArtist = 16, - AudioDbAlbum = 17 + AudioDbAlbum = 17, + MusicBrainzTrack = 18 } } diff --git a/MediaBrowser.Model/Sync/SyncJobCreationResult.cs b/MediaBrowser.Model/Sync/SyncJobCreationResult.cs index 797318b2a..6723aa2cf 100644 --- a/MediaBrowser.Model/Sync/SyncJobCreationResult.cs +++ b/MediaBrowser.Model/Sync/SyncJobCreationResult.cs @@ -1,8 +1,15 @@ - +using System.Collections.Generic; + namespace MediaBrowser.Model.Sync { public class SyncJobCreationResult { public SyncJob Job { get; set; } + public List JobItems { get; set; } + + public SyncJobCreationResult() + { + JobItems = new List(); + } } } diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index c5c6880e1..a8e16e4ae 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -1,6 +1,5 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -9,6 +8,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; using System; using System.Collections.Generic; using System.Globalization; @@ -16,7 +16,6 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Net; namespace MediaBrowser.Providers.Manager { diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index b51af0d8a..ad2b6ed0f 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -187,18 +187,27 @@ namespace MediaBrowser.Providers.MediaInfo audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album"); - var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist"); + var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists"); - if (string.IsNullOrWhiteSpace(artist)) + if (!string.IsNullOrWhiteSpace(artists)) { - audio.Artists.Clear(); + audio.Artists = artists.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); } else { - audio.Artists = SplitArtists(artist) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList(); - + var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist"); + if (string.IsNullOrWhiteSpace(artist)) + { + audio.Artists.Clear(); + } + else + { + audio.Artists = SplitArtists(artist) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + } } var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist") ?? FFProbeHelpers.GetDictionaryValue(tags, "album artist") ?? FFProbeHelpers.GetDictionaryValue(tags, "album_artist"); @@ -250,10 +259,23 @@ namespace MediaBrowser.Providers.MediaInfo FetchStudios(audio, tags, "publisher"); } - audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")); - audio.SetProviderId(MetadataProviders.MusicBrainzArtist, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")); + // These support mulitple values, but for now we only store the first. + audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id"))); + audio.SetProviderId(MetadataProviders.MusicBrainzArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id"))); + audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")); audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")); + audio.SetProviderId(MetadataProviders.MusicBrainzTrack, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")); + } + + private string GetMultipleMusicBrainzId(string value) + { + if (string.IsNullOrWhiteSpace(value)) + { + return null; + } + + return value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); } private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' }; diff --git a/MediaBrowser.Providers/Music/MusicExternalIds.cs b/MediaBrowser.Providers/Music/MusicExternalIds.cs index a4eab1eee..bcafdc6f6 100644 --- a/MediaBrowser.Providers/Music/MusicExternalIds.cs +++ b/MediaBrowser.Providers/Music/MusicExternalIds.cs @@ -118,4 +118,27 @@ namespace MediaBrowser.Providers.Music return item is Audio || item is MusicAlbum; } } + + public class MusicBrainzTrackId : IExternalId + { + public string Name + { + get { return "MusicBrainz Track"; } + } + + public string Key + { + get { return MetadataProviders.MusicBrainzTrack.ToString(); } + } + + public string UrlFormatString + { + get { return "http://musicbrainz.org/track/{0}"; } + } + + public bool Supports(IHasProviderIds item) + { + return item is Audio; + } + } } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 124bb396e..d7ea444a3 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -13,7 +13,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Naming.Audio; @@ -579,7 +578,7 @@ namespace MediaBrowser.Server.Implementations.Library collectionType = GetContentTypeOverride(fullPath, true); } - var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, this, directoryService) + var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService) { Parent = parent, Path = fullPath, @@ -753,12 +752,14 @@ namespace MediaBrowser.Server.Implementations.Library Directory.CreateDirectory(userRootPath); - _userRootFolder = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder; + var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder; - if (_userRootFolder == null) + if (tmpItem == null) { - _userRootFolder = (UserRootFolder)ResolvePath(new DirectoryInfo(userRootPath)); + tmpItem = (UserRootFolder)ResolvePath(new DirectoryInfo(userRootPath)); } + + _userRootFolder = tmpItem; } } } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index 0a41a6c04..31b2d8b0f 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.IO; +using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; @@ -11,10 +12,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers class SpecialFolderResolver : FolderResolver { private readonly IFileSystem _fileSystem; + private readonly IServerApplicationPaths _appPaths; - public SpecialFolderResolver(IFileSystem fileSystem) + public SpecialFolderResolver(IFileSystem fileSystem, IServerApplicationPaths appPaths) { _fileSystem = fileSystem; + _appPaths = appPaths; } /// @@ -39,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers { return new AggregateFolder(); } - if (args.IsRoot) + if (string.Equals(args.Path, _appPaths.DefaultUserViewsPath, StringComparison.OrdinalIgnoreCase)) { return new UserRootFolder(); //if we got here and still a root - must be user root } diff --git a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 8707f2e5b..c7bbca060 100644 --- a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -72,6 +72,8 @@ namespace MediaBrowser.Server.Implementations.Sorting private int CompareEpisodeToSpecial(Episode x, Episode y) { + // http://thetvdb.com/wiki/index.php?title=Special_Episodes + var xSeason = x.PhysicalSeasonNumber ?? -1; var ySeason = y.AirsAfterSeasonNumber ?? y.AirsBeforeSeasonNumber ?? -1; diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index cdbb0d5e5..71bc0e46b 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -158,9 +158,16 @@ namespace MediaBrowser.Server.Implementations.Sync }, _logger); } + jobItemsResult = _repo.GetJobItems(new SyncJobItemQuery + { + Statuses = new List { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting }, + JobId = jobId + }); + return new SyncJobCreationResult { - Job = GetJob(jobId) + Job = GetJob(jobId), + JobItems = jobItemsResult.Items.ToList() }; } -- cgit v1.2.3 From b6d59c7688fc39d4689bc9070a7a99271d5b41ee Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 6 Feb 2015 00:39:07 -0500 Subject: fixes #1001 - Support downloading --- MediaBrowser.Api/Library/LibraryService.cs | 56 +++++++++++++++------- MediaBrowser.Api/Playback/BaseStreamingService.cs | 12 ++--- .../Playback/Progressive/VideoService.cs | 1 + MediaBrowser.Controller/Channels/Channel.cs | 5 ++ .../Channels/ChannelAudioItem.cs | 7 ++- .../Channels/ChannelFolderItem.cs | 12 +++-- .../Channels/ChannelVideoItem.cs | 7 ++- .../Entities/AggregateFolder.cs | 5 ++ MediaBrowser.Controller/Entities/Audio/Audio.cs | 7 +++ .../Entities/Audio/MusicArtist.cs | 12 +++-- .../Entities/Audio/MusicGenre.cs | 5 ++ MediaBrowser.Controller/Entities/BaseItem.cs | 32 +++++++++++++ .../Entities/BasePluginFolder.cs | 5 ++ MediaBrowser.Controller/Entities/Book.cs | 8 ++++ .../Entities/CollectionFolder.cs | 5 ++ MediaBrowser.Controller/Entities/Game.cs | 9 +++- MediaBrowser.Controller/Entities/GameGenre.cs | 5 ++ MediaBrowser.Controller/Entities/Genre.cs | 5 ++ MediaBrowser.Controller/Entities/IItemByName.cs | 4 ++ MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 5 ++ MediaBrowser.Controller/Entities/Person.cs | 5 ++ MediaBrowser.Controller/Entities/Studio.cs | 5 ++ MediaBrowser.Controller/Entities/UserView.cs | 5 ++ MediaBrowser.Controller/Entities/Video.cs | 13 +++++ MediaBrowser.Controller/Entities/Year.cs | 5 ++ MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs | 4 ++ .../LiveTv/LiveTvAudioRecording.cs | 6 +++ MediaBrowser.Controller/LiveTv/LiveTvChannel.cs | 9 +++- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 13 +++-- .../LiveTv/LiveTvVideoRecording.cs | 5 ++ MediaBrowser.Controller/Playlists/Playlist.cs | 7 ++- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 8 ++-- MediaBrowser.Model/Dto/BaseItemDto.cs | 2 + MediaBrowser.Model/LiveTv/RecordingInfoDto.cs | 6 +++ MediaBrowser.Model/Querying/ItemFields.cs | 13 ++++- MediaBrowser.Model/Users/UserPolicy.cs | 5 +- .../Dto/DtoService.cs | 14 ++++++ .../HttpServer/Security/AuthService.cs | 26 +++++++++- .../LiveTv/LiveTvDtoService.cs | 4 ++ .../Localization/JavaScript/javascript.json | 2 + .../Localization/Server/server.json | 13 ++--- .../Sync/SyncJobProcessor.cs | 4 +- MediaBrowser.WebDashboard/Api/PackageCreator.cs | 1 - .../MediaBrowser.WebDashboard.csproj | 6 --- 44 files changed, 322 insertions(+), 66 deletions(-) (limited to 'MediaBrowser.Controller/Entities/CollectionFolder.cs') diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index f147234fe..a97e2b52e 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -226,6 +226,18 @@ namespace MediaBrowser.Api.Library public string TvdbId { get; set; } } + [Route("/Items/{Id}/Download", "GET", Summary = "Downloads item media")] + [Authenticated(Roles = "download")] + public class GetDownload + { + /// + /// 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; } + } + /// /// Class LibraryService /// @@ -273,7 +285,7 @@ namespace MediaBrowser.Api.Library } var dtoOptions = GetDtoOptions(request); - + var result = new ItemsResult { TotalRecordCount = items.Count, @@ -289,6 +301,28 @@ namespace MediaBrowser.Api.Library Task.Run(() => _libraryManager.ValidateMediaLibrary(new Progress(), CancellationToken.None)); } + public object Get(GetDownload request) + { + var item = _libraryManager.GetItemById(request.Id); + + if (!item.CanDelete()) + { + throw new ArgumentException("Item does not support downloading"); + } + + var headers = new Dictionary(); + + // Quotes are valid in linux. They'll possibly cause issues here + var filename = Path.GetFileName(item.Path).Replace("\"", string.Empty); + headers["Content-Disposition"] = string.Format("inline; filename=\"{0}\"", filename); + + return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions + { + Path = item.Path, + ResponseHeaders = headers + }); + } + public object Get(GetFile request) { var item = _libraryManager.GetItemById(request.Id); @@ -347,7 +381,7 @@ namespace MediaBrowser.Api.Library var dtoOptions = GetDtoOptions(request); BaseItem parent = item.Parent; - + while (parent != null) { if (user != null) @@ -458,23 +492,9 @@ namespace MediaBrowser.Api.Library var auth = _authContext.GetAuthorizationInfo(Request); var user = _userManager.GetUserById(auth.UserId); - if (item is Playlist || item is BoxSet) + if (!item.CanDelete(user)) { - // For now this is allowed if user can see the playlist - } - else if (item is ILiveTvRecording) - { - if (!user.Policy.EnableLiveTvManagement) - { - throw new UnauthorizedAccessException(); - } - } - else - { - if (!user.Policy.EnableContentDeletion) - { - throw new UnauthorizedAccessException(); - } + throw new UnauthorizedAccessException(); } var task = _libraryManager.DeleteItem(item); diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 6d555e136..d26ca2721 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -123,7 +123,7 @@ namespace MediaBrowser.Api.Playback private string GetOutputFilePath(StreamState state) { var folder = ServerConfigurationManager.ApplicationPaths.TranscodingTempPath; - + var outputFileExtension = GetOutputFileExtension(state); var data = GetCommandLineArguments("dummy\\dummy", "dummyTranscodingId", state, false); @@ -323,13 +323,13 @@ namespace MediaBrowser.Api.Playback switch (qualitySetting) { case EncodingQuality.HighSpeed: - param += " -crf 23"; + param += " -subq 0 -crf 23"; break; case EncodingQuality.HighQuality: - param += " -crf 20"; + param += " -subq 3 -crf 20"; break; case EncodingQuality.MaxQuality: - param += " -crf 18"; + param += " -subq 6 -crf 18"; break; } } @@ -507,7 +507,7 @@ namespace MediaBrowser.Api.Playback } } - return param; + return "-pix_fmt yuv420p " + param; } protected string GetAudioFilterParam(StreamState state, bool isHls) @@ -918,7 +918,7 @@ namespace MediaBrowser.Api.Playback if (SupportsThrottleWithStream) { var url = "http://localhost:" + ServerConfigurationManager.Configuration.HttpServerPortNumber.ToString(UsCulture) + "/videos/" + state.Request.Id + "/stream?static=true&Throttle=true&mediaSourceId=" + state.Request.MediaSourceId; - + url += "&transcodingJobId=" + transcodingJobId; return string.Format("\"{0}\"", url); diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 8924bb38f..7e86b867f 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -97,6 +97,7 @@ namespace MediaBrowser.Api.Playback.Progressive if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase)) { + // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js format = " -f mp4 -movflags frag_keyframe+empty_moov"; } diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs index 87d257f12..a482f45fe 100644 --- a/MediaBrowser.Controller/Channels/Channel.cs +++ b/MediaBrowser.Controller/Channels/Channel.cs @@ -67,5 +67,10 @@ namespace MediaBrowser.Controller.Channels { return System.IO.Path.Combine(basePath, "channels", id.ToString("N"), "metadata"); } + + public override bool CanDelete() + { + return false; + } } } diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs index d9330f8a3..91b2407be 100644 --- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs +++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs @@ -3,10 +3,10 @@ using MediaBrowser.Model.Channels; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; using System.Collections.Generic; using System.Linq; using System.Threading; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Channels { @@ -89,5 +89,10 @@ namespace MediaBrowser.Controller.Channels return list; } + + public override bool CanDelete() + { + return false; + } } } diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs index dce9840ed..7ba73d126 100644 --- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs +++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs @@ -1,11 +1,10 @@ -using System; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Users; +using System; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Channels { @@ -76,5 +75,10 @@ namespace MediaBrowser.Controller.Channels { return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); } + + public override bool CanDelete() + { + return false; + } } } diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs index e3fad56e9..d7d4483cd 100644 --- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs +++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs @@ -4,11 +4,11 @@ using MediaBrowser.Model.Channels; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Channels { @@ -119,5 +119,10 @@ namespace MediaBrowser.Controller.Channels { return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); } + + public override bool CanDelete() + { + return false; + } } } diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index af2cca5e6..66a0d551b 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -32,6 +32,11 @@ namespace MediaBrowser.Controller.Entities } } + public override bool CanDelete() + { + return false; + } + /// /// The _virtual children /// diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 2dcea37bd..a7b91b868 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -113,6 +113,13 @@ namespace MediaBrowser.Controller.Entities.Audio } } + public override bool CanDownload() + { + var locationType = LocationType; + return locationType != LocationType.Remote && + locationType != LocationType.Virtual; + } + /// /// Gets or sets the artist. /// diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 038aa98aa..e65d3c0e7 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -1,14 +1,13 @@ -using System.Runtime.Serialization; -using MediaBrowser.Common.Progress; -using MediaBrowser.Controller.Providers; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Entities.Audio { @@ -35,6 +34,11 @@ namespace MediaBrowser.Controller.Entities.Audio get { return true; } } + public override bool CanDelete() + { + return !IsAccessedByName; + } + protected override IEnumerable ActualChildren { get diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index 9689d7cce..ed0956073 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -39,6 +39,11 @@ namespace MediaBrowser.Controller.Entities.Audio } } + public override bool CanDelete() + { + return false; + } + /// /// Gets a value indicating whether this instance is owned item. /// diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 4925bcd8a..1443d99d3 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -239,6 +239,38 @@ namespace MediaBrowser.Controller.Entities get { return this.GetImagePath(ImageType.Primary); } } + public virtual bool CanDelete() + { + var locationType = LocationType; + return locationType != LocationType.Remote && + locationType != LocationType.Virtual; + } + + public virtual bool IsAuthorizedToDelete(User user) + { + return user.Policy.EnableContentDeletion; + } + + public bool CanDelete(User user) + { + return CanDelete() && IsAuthorizedToDelete(user); + } + + public virtual bool CanDownload() + { + return false; + } + + public virtual bool IsAuthorizedToDownload(User user) + { + return user.Policy.EnableContentDownloading; + } + + public bool CanDownload(User user) + { + return CanDownload() && IsAuthorizedToDownload(user); + } + /// /// Gets or sets the date created. /// diff --git a/MediaBrowser.Controller/Entities/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs index b30bd81b9..785c441d3 100644 --- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs +++ b/MediaBrowser.Controller/Entities/BasePluginFolder.cs @@ -11,5 +11,10 @@ namespace MediaBrowser.Controller.Entities { get { return null; } } + + public override bool CanDelete() + { + return false; + } } } diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs index 381b2101d..e59db67a6 100644 --- a/MediaBrowser.Controller/Entities/Book.cs +++ b/MediaBrowser.Controller/Entities/Book.cs @@ -2,6 +2,7 @@ using MediaBrowser.Model.Configuration; using System.Collections.Generic; using System.Linq; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Entities @@ -37,6 +38,13 @@ namespace MediaBrowser.Controller.Entities Tags = new List(); } + public override bool CanDownload() + { + var locationType = LocationType; + return locationType != LocationType.Remote && + locationType != LocationType.Virtual; + } + protected override bool GetBlockUnratedValue(UserPolicy config) { return config.BlockUnratedItems.Contains(UnratedItem.Book); diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index f82934a51..a39357f2b 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -35,6 +35,11 @@ namespace MediaBrowser.Controller.Entities } } + public override bool CanDelete() + { + return false; + } + public string CollectionType { get; set; } /// diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index 71642ea90..899e5628f 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -1,10 +1,10 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; using System; using System.Collections.Generic; using System.Linq; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Entities { @@ -38,6 +38,13 @@ namespace MediaBrowser.Controller.Entities public List LocalTrailerIds { get; set; } public List RemoteTrailerIds { get; set; } + public override bool CanDownload() + { + var locationType = LocationType; + return locationType != LocationType.Remote && + locationType != LocationType.Virtual; + } + /// /// Gets or sets the tags. /// diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index 41ce0c12a..b246b9388 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -43,6 +43,11 @@ namespace MediaBrowser.Controller.Entities } } + public override bool CanDelete() + { + return false; + } + public IEnumerable GetTaggedItems(IEnumerable inputItems) { return inputItems.Where(GetItemFilter()); diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index f581c55e8..e17a5c1d8 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -34,6 +34,11 @@ namespace MediaBrowser.Controller.Entities } } + public override bool CanDelete() + { + return false; + } + /// /// Gets a value indicating whether this instance is owned item. /// diff --git a/MediaBrowser.Controller/Entities/IItemByName.cs b/MediaBrowser.Controller/Entities/IItemByName.cs index b48ad788f..14b69b8fd 100644 --- a/MediaBrowser.Controller/Entities/IItemByName.cs +++ b/MediaBrowser.Controller/Entities/IItemByName.cs @@ -15,6 +15,10 @@ namespace MediaBrowser.Controller.Entities /// IEnumerable{BaseItem}. IEnumerable GetTaggedItems(IEnumerable inputItems); + /// + /// Gets the item filter. + /// + /// Func<BaseItem, System.Boolean>. Func GetItemFilter(); } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 7f74e3379..d874046ef 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -74,6 +74,11 @@ namespace MediaBrowser.Controller.Entities.Movies } } + public override bool IsAuthorizedToDelete(User user) + { + return true; + } + /// /// Gets the trailer ids. /// diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 25509b153..d8cb69ca1 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Entities } } + public override bool CanDelete() + { + return false; + } + /// /// Gets a value indicating whether this instance is owned item. /// diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 76193d6c4..31bbaf422 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -40,6 +40,11 @@ namespace MediaBrowser.Controller.Entities } } + public override bool CanDelete() + { + return false; + } + /// /// Gets a value indicating whether this instance is owned item. /// diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index cd179eb42..5f7ca3d3f 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -40,6 +40,11 @@ namespace MediaBrowser.Controller.Entities return result.Items; } + public override bool CanDelete() + { + return false; + } + public override IEnumerable GetRecursiveChildren(User user, Func filter) { var result = GetItems(new InternalItemsQuery diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 3abaf095c..12c377c90 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -64,6 +64,19 @@ namespace MediaBrowser.Controller.Entities LinkedAlternateVersions = new List(); } + public override bool CanDownload() + { + if (VideoType == VideoType.HdDvd || VideoType == VideoType.Dvd || + VideoType == VideoType.BluRay) + { + return false; + } + + var locationType = LocationType; + return locationType != LocationType.Remote && + locationType != LocationType.Virtual; + } + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index 59a4bf16d..cf3ad3b6a 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -34,6 +34,11 @@ namespace MediaBrowser.Controller.Entities } } + public override bool CanDelete() + { + return false; + } + /// /// Gets a value indicating whether this instance is owned item. /// diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs index ba1cb3043..784cb6ea1 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs @@ -25,5 +25,9 @@ namespace MediaBrowser.Controller.LiveTv Task RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken); PlayAccess GetPlayAccess(User user); + + bool CanDelete(); + + bool CanDelete(User user); } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index 8faaa895c..9815066ef 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -1,4 +1,5 @@ using System.Runtime.Serialization; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; @@ -93,5 +94,10 @@ namespace MediaBrowser.Controller.LiveTv { return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N")); } + + public override bool IsAuthorizedToDelete(User user) + { + return user.Policy.EnableLiveTvManagement; + } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 1948ce0d5..eaea6cfa4 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -1,5 +1,4 @@ -using System.Runtime.Serialization; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -8,6 +7,7 @@ using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Users; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; namespace MediaBrowser.Controller.LiveTv { @@ -135,5 +135,10 @@ namespace MediaBrowser.Controller.LiveTv { return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"), "metadata"); } + + public override bool CanDelete() + { + return false; + } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index a66aaad6f..ee85ce20b 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -1,13 +1,13 @@ -using System.Runtime.Serialization; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Users; using System; +using System.Linq; +using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; -using System.Linq; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.LiveTv { @@ -215,5 +215,10 @@ namespace MediaBrowser.Controller.LiveTv { return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N")); } + + public override bool CanDelete() + { + return false; + } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index 34fe757a7..207684d55 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -92,5 +92,10 @@ namespace MediaBrowser.Controller.LiveTv { return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N")); } + + public override bool IsAuthorizedToDelete(User user) + { + return user.Policy.EnableLiveTvManagement; + } } } diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index 0f0c6a97e..3479902cb 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -1,7 +1,5 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using System; @@ -40,6 +38,11 @@ namespace MediaBrowser.Controller.Playlists } } + public override bool IsAuthorizedToDelete(User user) + { + return true; + } + public override bool IsSaveLocalMetadataEnabled() { return true; diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 344eb9fbd..5a00c3d3f 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -631,13 +631,13 @@ namespace MediaBrowser.MediaEncoding.Encoder switch (qualitySetting) { case EncodingQuality.HighSpeed: - param += " -crf 23"; + param += " -subq 0 -crf 23"; break; case EncodingQuality.HighQuality: - param += " -crf 20"; + param += " -subq 3 -crf 20"; break; case EncodingQuality.MaxQuality: - param += " -crf 18"; + param += " -subq 6 -crf 18"; break; } } @@ -740,7 +740,7 @@ namespace MediaBrowser.MediaEncoding.Encoder param += " -level " + state.Options.Level.Value.ToString(UsCulture); } - return param; + return "-pix_fmt yuv420p " + param; } protected string GetVideoBitrateParam(EncodingJob state, string videoCodec, bool isHls) diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index c1a34a7f6..be3cd99be 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -56,6 +56,8 @@ namespace MediaBrowser.Model.Dto public int? AirsBeforeEpisodeNumber { get; set; } public int? AbsoluteEpisodeNumber { get; set; } public bool? DisplaySpecialsWithSeasons { get; set; } + public bool? CanDelete { get; set; } + public bool? CanDownload { get; set; } public string PreferredMetadataLanguage { get; set; } public string PreferredMetadataCountryCode { get; set; } diff --git a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs index 15378a9af..a6cd85d8d 100644 --- a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs @@ -99,6 +99,12 @@ namespace MediaBrowser.Model.LiveTv /// The path. public string Path { get; set; } + /// + /// Gets or sets a value indicating whether this instance can delete. + /// + /// null if [can delete] contains no value, true if [can delete]; otherwise, false. + public bool? CanDelete { get; set; } + /// /// Overview of the recording. /// diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index 5018f8e51..7a91d77ff 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -1,5 +1,4 @@ - -namespace MediaBrowser.Model.Querying +namespace MediaBrowser.Model.Querying { /// /// Used to control the data that gets attached to DtoBaseItems @@ -26,6 +25,16 @@ namespace MediaBrowser.Model.Querying /// Budget, + /// + /// The can delete + /// + CanDelete, + + /// + /// The can download + /// + CanDownload, + /// /// The chapters /// diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index cdc5077b0..9606cbe3f 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -42,7 +42,8 @@ namespace MediaBrowser.Model.Users public bool EnableMediaPlayback { get; set; } public bool EnableContentDeletion { get; set; } - + public bool EnableContentDownloading { get; set; } + /// /// Gets or sets a value indicating whether [enable synchronize]. /// @@ -80,6 +81,8 @@ namespace MediaBrowser.Model.Users EnabledDevices = new string[] { }; EnableAllDevices = true; + + EnableContentDownloading = true; } } } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 7b36321f1..75bddda72 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -284,6 +284,20 @@ namespace MediaBrowser.Server.Implementations.Dto AttachLinkedChildImages(dto, playlist, user, options); } + if (fields.Contains(ItemFields.CanDelete)) + { + dto.CanDelete = user == null + ? item.CanDelete() + : item.CanDelete(user); + } + + if (fields.Contains(ItemFields.CanDownload)) + { + dto.CanDownload = user == null + ? item.CanDownload() + : item.CanDownload(user); + } + return dto; } diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs index c374a31b3..77953ee43 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs @@ -74,7 +74,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security ValidateUserAccess(user, request, authAttribtues, auth); } - if (!IsExemptFromRoles(auth, authAttribtues)) + var info = (AuthenticationInfo)request.Items["OriginalAuthenticationInfo"]; + + if (!IsExemptFromRoles(auth, authAttribtues, info)) { var roles = authAttribtues.GetRoles().ToList(); @@ -142,7 +144,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security StringComparer.OrdinalIgnoreCase); } - private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues) + private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues, AuthenticationInfo tokenInfo) { if (!_config.Configuration.IsStartupWizardCompleted && authAttribtues.AllowBeforeStartupWizard) @@ -150,6 +152,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security return true; } + if (string.IsNullOrWhiteSpace(auth.Token)) + { + return true; + } + + if (tokenInfo != null && string.IsNullOrWhiteSpace(tokenInfo.UserId)) + { + return true; + } + return false; } @@ -175,6 +187,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security }; } } + if (roles.Contains("download", StringComparer.OrdinalIgnoreCase)) + { + if (user == null || !user.Policy.EnableContentDownloading) + { + throw new SecurityException("User does not have download access.") + { + SecurityExceptionType = SecurityExceptionType.Unauthenticated + }; + } + } } private bool IsValidConnectKey(string token) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs index b3066b460..f1bb5c13a 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -229,6 +229,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv ServerId = _appHost.SystemId }; + dto.CanDelete = user == null + ? recording.CanDelete() + : recording.CanDelete(user); + dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList(); if (info.Status == RecordingStatus.InProgress) diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index 3fddf274c..184a7f9a4 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -48,6 +48,7 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Save", + "ButtonDownload": "Download", "SyncJobStatusQueued": "Queued", "SyncJobStatusConverting": "Converting", "SyncJobStatusFailed": "Failed", @@ -56,6 +57,7 @@ "SyncJobStatusReadyToTransfer": "Ready to Transfer", "SyncJobStatusTransferring": "Transferring", "SyncJobStatusCompletedWithError": "Synced with errors", + "SyncJobItemStatusReadyToTransfer": "Ready to Transfer", "LabelCollection": "Collection", "HeaderAddToCollection": "Add to Collection", "NewCollectionNameExample": "Example: Star Wars Collection", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index aaf05d1ff..c280b32ea 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -285,10 +285,10 @@ "ButtonHelp": "Help", "OptionAllowUserToManageServer": "Allow this user to manage the server", "HeaderFeatureAccess": "Feature Access", - "OptionAllowMediaPlayback": "Allow media playback", - "OptionAllowBrowsingLiveTv": "Allow browsing of live tv", - "OptionAllowDeleteLibraryContent": "Allow deletion of library content", - "OptionAllowManageLiveTv": "Allow management of live tv recordings", + "OptionAllowMediaPlayback": "Media playback", + "OptionAllowBrowsingLiveTv": "Live TV", + "OptionAllowDeleteLibraryContent": "Media deletion", + "OptionAllowManageLiveTv": "Live TV recording management", "OptionAllowRemoteControlOthers": "Allow remote control of other users", "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices", "OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.", @@ -1133,7 +1133,7 @@ "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", "LabelEasyPinCode": "Easy pin code:", - "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", @@ -1362,7 +1362,8 @@ "LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.", "TabActivity": "Activity", "TitleSync": "Sync", - "OptionAllowSyncContent": "Allow syncing media to devices", + "OptionAllowSyncContent": "Sync", + "OptionAllowContentDownloading": "Media downloading", "NameSeasonUnknown": "Season Unknown", "NameSeasonNumber": "Season {0}", "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)", diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index e418448db..9ecb80f3b 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -311,8 +311,10 @@ namespace MediaBrowser.Server.Implementations.Sync var itemByName = item as IItemByName; if (itemByName != null) { + var itemByNameFilter = itemByName.GetItemFilter(); + return user.RootFolder - .GetRecursiveChildren(user, itemByName.GetItemFilter()); + .GetRecursiveChildren(user, i => !i.IsFolder && itemByNameFilter(i)); } if (item.IsFolder) diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs index 3eb98e95d..8bf005021 100644 --- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs +++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs @@ -414,7 +414,6 @@ namespace MediaBrowser.WebDashboard.Api "indexpage.js", "itembynamedetailpage.js", "itemdetailpage.js", - "itemgallery.js", "itemlistpage.js", "librarypathmapping.js", "reports.js", diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 34b0e9e88..bc610b7b6 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1656,9 +1656,6 @@ - - PreserveNewest - PreserveNewest @@ -1707,9 +1704,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest -- cgit v1.2.3