diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations')
9 files changed, 140 insertions, 60 deletions
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index d4d7f2f21..5bf6587a9 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -2,7 +2,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; @@ -28,10 +27,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private readonly IFileSystem _fileSystem; private readonly IFileOrganizationService _organizationService; private readonly IServerConfigurationManager _config; + private readonly IProviderManager _providerManager; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - public EpisodeFileOrganizer(IFileOrganizationService organizationService, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor) + public EpisodeFileOrganizer(IFileOrganizationService organizationService, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager) { _organizationService = organizationService; _config = config; @@ -39,9 +39,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _logger = logger; _libraryManager = libraryManager; _libraryMonitor = libraryMonitor; + _providerManager = providerManager; } - public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, TvFileOrganizationOptions options, bool overwriteExisting) + public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, TvFileOrganizationOptions options, bool overwriteExisting, CancellationToken cancellationToken) { _logger.Info("Sorting file {0}", path); @@ -77,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization result.ExtractedEndingEpisodeNumber = endingEpisodeNumber; - OrganizeEpisode(path, seriesName, season.Value, episode.Value, endingEpisodeNumber, options, overwriteExisting, result); + await OrganizeEpisode(path, seriesName, season.Value, episode.Value, endingEpisodeNumber, options, overwriteExisting, result, cancellationToken).ConfigureAwait(false); } else { @@ -119,20 +120,20 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return result; } - public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options) + public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options, CancellationToken cancellationToken) { var result = _organizationService.GetResult(request.ResultId); var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId)); - OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, _config.Configuration.TvFileOrganizationOptions, true, result); + await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, _config.Configuration.TvFileOrganizationOptions, true, result, cancellationToken).ConfigureAwait(false); await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false); return result; } - private void OrganizeEpisode(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result) + private Task OrganizeEpisode(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result, CancellationToken cancellationToken) { var series = GetMatchingSeries(seriesName, result); @@ -142,18 +143,18 @@ namespace MediaBrowser.Server.Implementations.FileOrganization result.Status = FileSortingStatus.Failure; result.StatusMessage = msg; _logger.Warn(msg); - return; + return Task.FromResult(true); } - OrganizeEpisode(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, overwriteExisting, result); + return OrganizeEpisode(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, overwriteExisting, result, cancellationToken); } - private void OrganizeEpisode(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result) + private async Task OrganizeEpisode(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result, CancellationToken cancellationToken) { _logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path); // Proceed to sort the file - var newPath = GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options); + var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(newPath)) { @@ -326,25 +327,33 @@ namespace MediaBrowser.Server.Implementations.FileOrganization /// <param name="endingEpisodeNumber">The ending episode number.</param> /// <param name="options">The options.</param> /// <returns>System.String.</returns> - private string GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, TvFileOrganizationOptions options) + private async Task<string> GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, TvFileOrganizationOptions options, CancellationToken cancellationToken) { - // If season and episode numbers match - var currentEpisodes = series.RecursiveChildren.OfType<Episode>() - .Where(i => i.IndexNumber.HasValue && - i.IndexNumber.Value == episodeNumber && - i.ParentIndexNumber.HasValue && - i.ParentIndexNumber.Value == seasonNumber) - .ToList(); + var episodeInfo = new EpisodeInfo + { + IndexNumber = episodeNumber, + IndexNumberEnd = endingEpisodeNumber, + MetadataCountryCode = series.GetPreferredMetadataCountryCode(), + MetadataLanguage = series.GetPreferredMetadataLanguage(), + ParentIndexNumber = seasonNumber, + SeriesProviderIds = series.ProviderIds + }; - if (currentEpisodes.Count == 0) + var searchResults = await _providerManager.GetRemoteSearchResults<Episode, EpisodeInfo>(new RemoteSearchQuery<EpisodeInfo> + { + SearchInfo = episodeInfo + + }, cancellationToken).ConfigureAwait(false); + + var episode = searchResults.FirstOrDefault(); + + if (episode == null) { return null; } var newPath = GetSeasonFolderPath(series, seasonNumber, options); - var episode = currentEpisodes.First(); - var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options); newPath = Path.Combine(newPath, episodeFileName); diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs index c03ceb6e5..7cf38b0a0 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs @@ -3,9 +3,9 @@ using MediaBrowser.Common.IO; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; @@ -25,8 +25,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private readonly ILibraryManager _libraryManager; private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; + private readonly IProviderManager _providerManager; - public FileOrganizationService(ITaskManager taskManager, IFileOrganizationRepository repo, ILogger logger, ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, IServerConfigurationManager config, IFileSystem fileSystem) + public FileOrganizationService(ITaskManager taskManager, IFileOrganizationRepository repo, ILogger logger, ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager) { _taskManager = taskManager; _repo = repo; @@ -35,6 +36,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _libraryManager = libraryManager; _config = config; _fileSystem = fileSystem; + _providerManager = providerManager; } public void BeginProcessNewFiles() @@ -103,9 +105,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, - _libraryMonitor); + _libraryMonitor, _providerManager); - await organizer.OrganizeEpisodeFile(result.OriginalPath, _config.Configuration.TvFileOrganizationOptions, true) + await organizer.OrganizeEpisodeFile(result.OriginalPath, _config.Configuration.TvFileOrganizationOptions, true, CancellationToken.None) .ConfigureAwait(false); } @@ -117,9 +119,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization public async Task PerformEpisodeOrganization(EpisodeFileOrganizationRequest request) { var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, - _libraryMonitor); + _libraryMonitor, _providerManager); - await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions).ConfigureAwait(false); + await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions, CancellationToken.None).ConfigureAwait(false); } } } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs index 3c5e1ed0e..fbb743f94 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs @@ -2,8 +2,8 @@ using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; @@ -20,8 +20,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _config; private readonly IFileOrganizationService _organizationService; + private readonly IProviderManager _providerManager; - public OrganizerScheduledTask(ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IServerConfigurationManager config, IFileOrganizationService organizationService) + public OrganizerScheduledTask(ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IServerConfigurationManager config, IFileOrganizationService organizationService, IProviderManager providerManager) { _libraryMonitor = libraryMonitor; _libraryManager = libraryManager; @@ -29,6 +30,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _fileSystem = fileSystem; _config = config; _organizationService = organizationService; + _providerManager = providerManager; } public string Name @@ -48,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization public Task Execute(CancellationToken cancellationToken, IProgress<double> progress) { - return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config) + return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config, _providerManager) .Organize(_config.Configuration.TvFileOrganizationOptions, cancellationToken, progress); } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs index 85b45cf2c..9df6e7f1c 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs @@ -1,8 +1,8 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.FileOrganization; @@ -24,8 +24,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private readonly IFileSystem _fileSystem; private readonly IFileOrganizationService _organizationService; private readonly IServerConfigurationManager _config; + private readonly IProviderManager _providerManager; - public TvFolderOrganizer(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IFileOrganizationService organizationService, IServerConfigurationManager config) + public TvFolderOrganizer(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IFileOrganizationService organizationService, IServerConfigurationManager config, IProviderManager providerManager) { _libraryManager = libraryManager; _logger = logger; @@ -33,6 +34,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _libraryMonitor = libraryMonitor; _organizationService = organizationService; _config = config; + _providerManager = providerManager; } public async Task Organize(TvFileOrganizationOptions options, CancellationToken cancellationToken, IProgress<double> progress) @@ -57,9 +59,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization foreach (var file in eligibleFiles) { var organizer = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager, - _libraryMonitor); + _libraryMonitor, _providerManager); - var result = await organizer.OrganizeEpisodeFile(file.FullName, options, false).ConfigureAwait(false); + var result = await organizer.OrganizeEpisodeFile(file.FullName, options, false, cancellationToken).ConfigureAwait(false); if (result.Status == FileSortingStatus.Success) { diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index b4c442ec8..009e4716d 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -1,4 +1,5 @@ -using Funq; +using System.Net.Sockets; +using Funq; using MediaBrowser.Common; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 8634919fc..fa1d4b0d5 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -3,7 +3,6 @@ using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations.ScheduledTasks; using Microsoft.Win32; diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 656e0993f..c2044476a 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -408,8 +408,14 @@ namespace MediaBrowser.Server.Implementations.Library LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; }); } - public async Task DeleteItem(BaseItem item) + public async Task DeleteItem(BaseItem item, DeleteOptions options) { + _logger.Debug("Deleting item, Type: {0}, Name: {1}, Path: {2}, Id: {3}", + item.GetType().Name, + item.Name, + item.Path ?? string.Empty, + item.Id); + var parent = item.Parent; var locationType = item.LocationType; @@ -436,7 +442,7 @@ namespace MediaBrowser.Server.Implementations.Library } } - if (locationType == LocationType.FileSystem || locationType == LocationType.Offline) + if (options.DeleteFileLocation && (locationType == LocationType.FileSystem || locationType == LocationType.Offline)) { foreach (var path in item.GetDeletePaths().ToList()) { @@ -462,15 +468,14 @@ namespace MediaBrowser.Server.Implementations.Library { await parent.RemoveChild(item, CancellationToken.None).ConfigureAwait(false); } - else - { - throw new InvalidOperationException("Don't know how to delete " + item.Name); - } + await ItemRepository.DeleteItem(item.Id, CancellationToken.None).ConfigureAwait(false); foreach (var child in children) { await ItemRepository.DeleteItem(child.Id, CancellationToken.None).ConfigureAwait(false); } + + ReportItemRemoved(item); } private IEnumerable<string> GetMetadataPaths(BaseItem item, IEnumerable<BaseItem> children) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index f25cf541b..989ed3c35 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -726,7 +726,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv foreach (var channelInfo in allChannelsList) { cancellationToken.ThrowIfCancellationRequested(); - + try { var item = await GetChannel(channelInfo.Item2, channelInfo.Item1, cancellationToken).ConfigureAwait(false); @@ -764,7 +764,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv foreach (var item in list) { cancellationToken.ThrowIfCancellationRequested(); - + // Avoid implicitly captured closure var currentChannel = item; @@ -793,17 +793,44 @@ namespace MediaBrowser.Server.Implementations.LiveTv double percent = numComplete; percent /= allChannelsList.Count; - progress.Report(80 * percent + 10); + progress.Report(70 * percent + 10); } _programs = programs.ToDictionary(i => i.Id); + progress.Report(80); // Load these now which will prefetch metadata await GetRecordings(new RecordingQuery(), cancellationToken).ConfigureAwait(false); - + progress.Report(85); + + await DeleteOldPrograms(_programs.Keys.ToList(), progress, cancellationToken).ConfigureAwait(false); + progress.Report(100); } + private async Task DeleteOldPrograms(List<Guid> currentIdList, IProgress<double> progress, CancellationToken cancellationToken) + { + var list = _itemRepo.GetItemsOfType(typeof(LiveTvProgram)).ToList(); + + var numComplete = 0; + + foreach (var program in list) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (!currentIdList.Contains(program.Id)) + { + await _libraryManager.DeleteItem(program).ConfigureAwait(false); + } + + numComplete++; + double percent = numComplete; + percent /= list.Count; + + progress.Report(15 * percent + 85); + } + } + private double GetGuideDays(int channelCount) { if (_config.Configuration.LiveTvOptions.GuideDays.HasValue) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 1098dbf6d..70362654e 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -281,25 +281,30 @@ namespace MediaBrowser.Server.Implementations.Persistence { if (reader.Read()) { - var typeString = reader.GetString(0); + return GetItem(reader); + } + } + return null; + } + } - var type = _typeMapper.GetType(typeString); + private BaseItem GetItem(IDataReader reader) + { + var typeString = reader.GetString(0); - if (type == null) - { - _logger.Debug("Unknown type {0}", typeString); + var type = _typeMapper.GetType(typeString); - return null; - } + if (type == null) + { + _logger.Debug("Unknown type {0}", typeString); - using (var stream = reader.GetMemoryStream(1)) - { - return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem; - } - } - } return null; } + + using (var stream = reader.GetMemoryStream(1)) + { + return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem; + } } /// <summary> @@ -468,6 +473,34 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + public IEnumerable<BaseItem> GetItemsOfType(Type type) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } + + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "select type,data from TypedBaseItems where type = @type"; + + cmd.Parameters.Add(cmd, "@type", DbType.String).Value = type.FullName; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + var item = GetItem(reader); + + if (item != null) + { + yield return item; + } + } + } + } + } + public async Task DeleteItem(Guid id, CancellationToken cancellationToken) { if (id == Guid.Empty) |
