diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations')
8 files changed, 319 insertions, 119 deletions
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 7fa299050..7a9735e0e 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -649,11 +649,6 @@ namespace MediaBrowser.Server.Implementations.Dto dto.DateCreated = item.DateCreated; } - if (fields.Contains(ItemFields.OriginalRunTimeTicks)) - { - dto.OriginalRunTimeTicks = item.OriginalRunTimeTicks; - } - dto.DisplayMediaType = item.DisplayMediaType; if (fields.Contains(ItemFields.Settings)) diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index f9f54199f..ece21df7a 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -1,20 +1,21 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; 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; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.FileOrganization @@ -28,7 +29,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private readonly IFileOrganizationService _organizationService; private readonly IServerConfigurationManager _config; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); public EpisodeFileOrganizer(IFileOrganizationService organizationService, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, IDirectoryWatchers directoryWatchers) { @@ -154,28 +155,79 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _logger.Info("Sorting file {0} to new path {1}", sourcePath, newPath); result.TargetPath = newPath; - var existing = GetDuplicatePaths(result.TargetPath, series, seasonNumber, episodeNumber); + var fileExists = File.Exists(result.TargetPath); + var otherDuplicatePaths = GetOtherDuplicatePaths(result.TargetPath, series, seasonNumber, episodeNumber, endingEpiosdeNumber); - if (!overwriteExisting && existing.Count > 0) + if (!overwriteExisting && (fileExists || otherDuplicatePaths.Count > 0)) { result.Status = FileSortingStatus.SkippedExisting; result.StatusMessage = string.Empty; + result.DuplicatePaths = otherDuplicatePaths; return; } PerformFileSorting(options, result); + + if (overwriteExisting) + { + foreach (var path in otherDuplicatePaths) + { + _logger.Debug("Removing duplicate episode {0}", path); + + try + { + File.Delete(path); + } + catch (IOException ex) + { + _logger.ErrorException("Error removing duplicate episode", ex, path); + } + } + } } - private List<string> GetDuplicatePaths(string targetPath, Series series, int seasonNumber, int episodeNumber) + private List<string> GetOtherDuplicatePaths(string targetPath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber) { - var list = new List<string>(); + var episodePaths = series.RecursiveChildren + .OfType<Episode>() + .Where(i => + { + var locationType = i.LocationType; + + // Must be file system based and match exactly + if (locationType != LocationType.Remote && + locationType != LocationType.Virtual && + i.ParentIndexNumber.HasValue && + i.ParentIndexNumber.Value == seasonNumber && + i.IndexNumber.HasValue && + i.IndexNumber.Value == episodeNumber) + { - if (File.Exists(targetPath)) - { - list.Add(targetPath); - } + if (endingEpisodeNumber.HasValue || i.IndexNumberEnd.HasValue) + { + return endingEpisodeNumber.HasValue && i.IndexNumberEnd.HasValue && + endingEpisodeNumber.Value == i.IndexNumberEnd.Value; + } + + return true; + } - return list; + return false; + }) + .Select(i => i.Path) + .ToList(); + + var folder = Path.GetDirectoryName(targetPath); + var targetFileNameWithoutExtension = Path.GetFileNameWithoutExtension(targetPath); + + var filesOfOtherExtensions = Directory.EnumerateFiles(folder, "*", SearchOption.TopDirectoryOnly) + .Where(i => EntityResolutionHelper.IsVideoFile(i) && string.Equals(Path.GetFileNameWithoutExtension(i), targetFileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)); + + episodePaths.AddRange(filesOfOtherExtensions); + + return episodePaths.Where(i => !string.Equals(i, targetPath, StringComparison.OrdinalIgnoreCase)) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); } private void PerformFileSorting(TvFileOrganizationOptions options, FileOrganizationResult result) @@ -185,7 +237,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization Directory.CreateDirectory(Path.GetDirectoryName(result.TargetPath)); var copy = File.Exists(result.TargetPath); - + try { if (copy) diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index d8af92991..5b9e73996 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV } // If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something - if (season != null || parent.Parents.OfType<Series>().Any()) + if (season != null || parent is Series || parent.Parents.OfType<Series>().Any()) { Episode episode = null; diff --git a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs index d04ebe32d..f1e10e175 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs @@ -76,22 +76,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv private async Task<bool> DownloadImage(LiveTvChannel item, CancellationToken cancellationToken) { - var channelInfo = item.ChannelInfo; - Stream imageStream = null; string contentType = null; - if (!string.IsNullOrEmpty(channelInfo.ImagePath)) + if (!string.IsNullOrEmpty(item.ProviderImagePath)) { - contentType = "image/" + Path.GetExtension(channelInfo.ImagePath).ToLower(); - imageStream = _fileSystem.GetFileStream(channelInfo.ImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true); + contentType = "image/" + Path.GetExtension(item.ProviderImagePath).ToLower(); + imageStream = _fileSystem.GetFileStream(item.ProviderImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true); } - else if (!string.IsNullOrEmpty(channelInfo.ImageUrl)) + else if (!string.IsNullOrEmpty(item.ProviderImageUrl)) { var options = new HttpRequestOptions { CancellationToken = cancellationToken, - Url = channelInfo.ImageUrl + Url = item.ProviderImageUrl }; var response = await _httpClient.GetResponse(options).ConfigureAwait(false); @@ -105,7 +103,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv imageStream = response.Content; contentType = response.ContentType; } - else if (channelInfo.HasImage ?? true) + else if (item.HasProviderImage ?? true) { var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, item.ServiceName, StringComparison.OrdinalIgnoreCase)); @@ -113,7 +111,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { try { - var response = await service.GetChannelImageAsync(channelInfo.Id, cancellationToken).ConfigureAwait(false); + var response = await service.GetChannelImageAsync(item.ExternalId, cancellationToken).ConfigureAwait(false); if (response != null) { @@ -131,7 +129,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (imageStream != null) { // Dummy up the original url - var url = item.ServiceName + channelInfo.Id; + var url = item.ServiceName + item.ExternalId; await _providerManager.SaveImage(item, imageStream, contentType, ImageType.Primary, null, url, cancellationToken).ConfigureAwait(false); return true; diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs index 2fea919b0..4805adb1f 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (channel != null) { - dto.ChannelName = channel.ChannelInfo.Name; + dto.ChannelName = channel.Name; } return dto; @@ -224,7 +224,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery { - ItemId = recording.Id + ItemId = recording.Id }).ToList() }; @@ -271,6 +271,32 @@ namespace MediaBrowser.Server.Implementations.LiveTv return dto; } + public LiveTvTunerInfoDto GetTunerInfoDto(string serviceName, LiveTvTunerInfo info, string channelName) + { + var dto = new LiveTvTunerInfoDto + { + Name = info.Name, + Id = info.Id, + Clients = info.Clients, + ProgramName = info.ProgramName, + SourceType = info.SourceType, + Status = info.Status, + ChannelName = channelName + }; + + if (!string.IsNullOrEmpty(info.ChannelId)) + { + dto.ChannelId = GetInternalChannelId(serviceName, info.ChannelId).ToString("N"); + } + + if (!string.IsNullOrEmpty(info.RecordingId)) + { + dto.RecordingId = GetInternalRecordingId(serviceName, info.RecordingId).ToString("N"); + } + + return dto; + } + /// <summary> /// Gets the channel info dto. /// </summary> @@ -280,18 +306,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv /// <returns>ChannelInfoDto.</returns> public ChannelInfoDto GetChannelInfoDto(LiveTvChannel info, LiveTvProgram currentProgram, User user = null) { - var channelInfo = info.ChannelInfo; - var dto = new ChannelInfoDto { Name = info.Name, ServiceName = info.ServiceName, - ChannelType = channelInfo.ChannelType, - Number = channelInfo.Number, + ChannelType = info.ChannelType, + Number = info.Number, Type = info.GetClientTypeName(), Id = info.Id.ToString("N"), MediaType = info.MediaType, - ExternalId = channelInfo.Id + ExternalId = info.ExternalId }; if (user != null) @@ -316,37 +340,40 @@ namespace MediaBrowser.Server.Implementations.LiveTv public ProgramInfoDto GetProgramInfoDto(LiveTvProgram item, LiveTvChannel channel, User user = null) { - var program = item.ProgramInfo; - var dto = new ProgramInfoDto { - Id = GetInternalProgramId(item.ServiceName, program.Id).ToString("N"), - ChannelId = GetInternalChannelId(item.ServiceName, program.ChannelId).ToString("N"), - Overview = program.Overview, - EndDate = program.EndDate, - Genres = program.Genres, - ExternalId = program.Id, - Name = program.Name, + Id = GetInternalProgramId(item.ServiceName, item.ExternalId).ToString("N"), + ChannelId = GetInternalChannelId(item.ServiceName, item.ExternalChannelId).ToString("N"), + Overview = item.Overview, + Genres = item.Genres, + ExternalId = item.ExternalId, + Name = item.Name, ServiceName = item.ServiceName, - StartDate = program.StartDate, - OfficialRating = program.OfficialRating, - IsHD = program.IsHD, - OriginalAirDate = program.OriginalAirDate, - Audio = program.Audio, - CommunityRating = GetClientCommunityRating(program.CommunityRating), - IsRepeat = program.IsRepeat, - EpisodeTitle = program.EpisodeTitle, - IsMovie = program.IsMovie, - IsSeries = program.IsSeries, - IsSports = program.IsSports, - IsLive = program.IsLive, - IsNews = program.IsNews, - IsKids = program.IsKids, - IsPremiere = program.IsPremiere, - RunTimeTicks = (program.EndDate - program.StartDate).Ticks, + StartDate = item.StartDate, + OfficialRating = item.OfficialRating, + IsHD = item.IsHD, + OriginalAirDate = item.PremiereDate, + Audio = item.Audio, + CommunityRating = GetClientCommunityRating(item.CommunityRating), + IsRepeat = item.IsRepeat, + EpisodeTitle = item.EpisodeTitle, + IsMovie = item.IsMovie, + IsSeries = item.IsSeries, + IsSports = item.IsSports, + IsLive = item.IsLive, + IsNews = item.IsNews, + IsKids = item.IsKids, + IsPremiere = item.IsPremiere, Type = "Program" }; + if (item.EndDate.HasValue) + { + dto.EndDate = item.EndDate.Value; + + dto.RunTimeTicks = (item.EndDate.Value - item.StartDate).Ticks; + } + if (channel != null) { dto.ChannelName = channel.Name; diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index f62efd9da..e256d7da5 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1,7 +1,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; @@ -126,9 +125,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv { double number = 0; - if (!string.IsNullOrEmpty(i.ChannelInfo.Number)) + if (!string.IsNullOrEmpty(i.Number)) { - double.TryParse(i.ChannelInfo.Number, out number); + double.TryParse(i.Number, out number); } return number; @@ -140,9 +139,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv { double number = 0; - if (!string.IsNullOrEmpty(i.ChannelInfo.Number)) + if (!string.IsNullOrEmpty(i.Number)) { - double.TryParse(i.ChannelInfo.Number, out number); + double.TryParse(i.Number, out number); } return number; @@ -163,7 +162,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv } var returnChannels = allEnumerable - .Select(i => _tvDtoService.GetChannelInfoDto(i, GetCurrentProgram(i.ChannelInfo.Id), user)) + .Select(i => _tvDtoService.GetChannelInfoDto(i, GetCurrentProgram(i.ExternalId), user)) .ToArray(); var result = new QueryResult<ChannelInfoDto> @@ -251,9 +250,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv var channel = GetInternalChannel(id); - _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ChannelInfo.Id); + _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId); - var result = await service.GetChannelStream(channel.ChannelInfo.Id, cancellationToken).ConfigureAwait(false); + var result = await service.GetChannelStream(channel.ExternalId, cancellationToken).ConfigureAwait(false); if (!string.IsNullOrEmpty(result.Id)) { @@ -313,8 +312,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv isNew = true; } - item.ChannelInfo = channelInfo; + item.ChannelType = channelInfo.ChannelType; + item.ProviderImageUrl = channelInfo.ImageUrl; + item.HasProviderImage = channelInfo.HasImage; + item.ProviderImagePath = channelInfo.ImagePath; + item.ExternalId = channelInfo.Id; item.ServiceName = serviceName; + item.Number = channelInfo.Number; + + if (string.IsNullOrEmpty(item.Name)) + { + item.Name = channelInfo.Name; + } // Set this now so we don't cause additional file system access during provider executions item.ResetResolveArgs(fileInfo); @@ -346,9 +355,34 @@ namespace MediaBrowser.Server.Implementations.LiveTv } item.ChannelType = channelType; - item.ProgramInfo = info; item.ServiceName = serviceName; + item.Audio = info.Audio; + item.ExternalChannelId = info.ChannelId; + item.CommunityRating = info.CommunityRating; + item.EndDate = info.EndDate; + item.EpisodeTitle = info.EpisodeTitle; + item.ExternalId = info.Id; + item.Genres = info.Genres; + item.HasProviderImage = info.HasImage; + item.IsHD = info.IsHD; + item.IsKids = info.IsKids; + item.IsLive = info.IsLive; + item.IsMovie = info.IsMovie; + item.IsNews = info.IsNews; + item.IsPremiere = info.IsPremiere; + item.IsRepeat = info.IsRepeat; + item.IsSeries = info.IsSeries; + item.IsSports = info.IsSports; + item.Name = info.Name; + item.OfficialRating = info.OfficialRating; + item.Overview = info.Overview; + item.PremiereDate = info.OriginalAirDate; + item.ProviderImagePath = info.ImagePath; + item.ProviderImageUrl = info.ImageUrl; + item.RunTimeTicks = (info.EndDate - info.StartDate).Ticks; + item.StartDate = info.StartDate; + await item.RefreshMetadata(cancellationToken, forceSave: isNew, resetResolveArgs: false); return item; @@ -410,7 +444,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv private LiveTvChannel GetChannel(LiveTvProgram program) { - var programChannelId = program.ProgramInfo.ChannelId; + var programChannelId = program.ExternalChannelId; var internalProgramChannelId = _tvDtoService.GetInternalChannelId(program.ServiceName, programChannelId); @@ -438,28 +472,28 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var val = query.MinEndDate.Value; - programs = programs.Where(i => i.ProgramInfo.EndDate >= val); + programs = programs.Where(i => i.EndDate.HasValue && i.EndDate.Value >= val); } if (query.MinStartDate.HasValue) { var val = query.MinStartDate.Value; - programs = programs.Where(i => i.ProgramInfo.StartDate >= val); + programs = programs.Where(i => i.StartDate >= val); } if (query.MaxEndDate.HasValue) { var val = query.MaxEndDate.Value; - programs = programs.Where(i => i.ProgramInfo.EndDate <= val); + programs = programs.Where(i => i.EndDate.HasValue && i.EndDate.Value <= val); } if (query.MaxStartDate.HasValue) { var val = query.MaxStartDate.Value; - programs = programs.Where(i => i.ProgramInfo.StartDate <= val); + programs = programs.Where(i => i.StartDate <= val); } if (query.ChannelIdList.Length > 0) @@ -469,7 +503,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv programs = programs.Where(i => { - var programChannelId = i.ProgramInfo.ChannelId; + var programChannelId = i.ExternalChannelId; var internalProgramChannelId = _tvDtoService.GetInternalChannelId(serviceName, programChannelId); @@ -537,13 +571,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv .Select(i => _libraryManager.GetGenre(i)) .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); - programs = programList.OrderByDescending(i => GetRecommendationScore(i.ProgramInfo, user.Id, serviceName, genres)) - .ThenBy(i => i.ProgramInfo.StartDate); + programs = programList.OrderByDescending(i => GetRecommendationScore(i, user.Id, serviceName, genres)) + .ThenBy(i => i.StartDate); if (query.Limit.HasValue) { programs = programs.Take(query.Limit.Value) - .OrderBy(i => i.ProgramInfo.StartDate); + .OrderBy(i => i.StartDate); } var returnArray = programs @@ -566,7 +600,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv return result; } - private int GetRecommendationScore(ProgramInfo program, Guid userId, string serviceName, Dictionary<string, Genre> genres) + private int GetRecommendationScore(LiveTvProgram program, Guid userId, string serviceName, Dictionary<string, Genre> genres) { var score = 0; @@ -580,7 +614,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv score++; } - var internalChannelId = _tvDtoService.GetInternalChannelId(serviceName, program.ChannelId); + var internalChannelId = _tvDtoService.GetInternalChannelId(serviceName, program.ExternalChannelId); var channel = GetInternalChannel(internalChannelId); var channelUserdata = _userDataManager.GetUserData(userId, channel.GetUserDataKey()); @@ -724,9 +758,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv var start = DateTime.UtcNow.AddHours(-1); var end = start.AddDays(guideDays); - var channelPrograms = await service.GetProgramsAsync(currentChannel.ChannelInfo.Id, start, end, cancellationToken).ConfigureAwait(false); + var channelPrograms = await service.GetProgramsAsync(currentChannel.ExternalId, start, end, cancellationToken).ConfigureAwait(false); - var programTasks = channelPrograms.Select(program => GetProgram(program, currentChannel.ChannelInfo.ChannelType, service.Name, cancellationToken)); + var programTasks = channelPrograms.Select(program => GetProgram(program, currentChannel.ChannelType, service.Name, cancellationToken)); var programEntities = await Task.WhenAll(programTasks).ConfigureAwait(false); programs.AddRange(programEntities); @@ -1033,7 +1067,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var internalChannelId = _tvDtoService.GetInternalChannelId(service.Name, i.ChannelId); var channel = GetInternalChannel(internalChannelId); - channelName = channel == null ? null : channel.ChannelInfo.Name; + channelName = channel == null ? null : channel.Name; } return _tvDtoService.GetSeriesTimerInfoDto(i, service, channelName); @@ -1052,7 +1086,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var channel = GetInternalChannel(id); - var dto = _tvDtoService.GetChannelInfoDto(channel, GetCurrentProgram(channel.ChannelInfo.Id), user); + var dto = _tvDtoService.GetChannelInfoDto(channel, GetCurrentProgram(channel.ExternalId), user); return Task.FromResult(dto); } @@ -1062,15 +1096,48 @@ namespace MediaBrowser.Server.Implementations.LiveTv var now = DateTime.UtcNow; return _programs.Values - .Where(i => string.Equals(externalChannelId, i.ProgramInfo.ChannelId, StringComparison.OrdinalIgnoreCase)) - .OrderBy(i => i.ProgramInfo.StartDate) - .SkipWhile(i => now >= i.ProgramInfo.EndDate) + .Where(i => string.Equals(externalChannelId, i.ExternalChannelId, StringComparison.OrdinalIgnoreCase)) + .OrderBy(i => i.StartDate) + .SkipWhile(i => now >= (i.EndDate ?? DateTime.MinValue)) .FirstOrDefault(); } - private async Task<SeriesTimerInfo> GetNewTimerDefaultsInternal(CancellationToken cancellationToken, ProgramInfo program = null) + private async Task<SeriesTimerInfo> GetNewTimerDefaultsInternal(CancellationToken cancellationToken, LiveTvProgram program = null) { - var info = await ActiveService.GetNewTimerDefaultsAsync(cancellationToken, program).ConfigureAwait(false); + ProgramInfo programInfo = null; + + if (program != null) + { + programInfo = new ProgramInfo + { + Audio = program.Audio, + ChannelId = program.ExternalChannelId, + CommunityRating = program.CommunityRating, + EndDate = program.EndDate ?? DateTime.MinValue, + EpisodeTitle = program.EpisodeTitle, + Genres = program.Genres, + HasImage = program.HasProviderImage, + Id = program.ExternalId, + IsHD = program.IsHD, + IsKids = program.IsKids, + IsLive = program.IsLive, + IsMovie = program.IsMovie, + IsNews = program.IsNews, + IsPremiere = program.IsPremiere, + IsRepeat = program.IsRepeat, + IsSeries = program.IsSeries, + IsSports = program.IsSports, + OriginalAirDate = program.PremiereDate, + Overview = program.Overview, + StartDate = program.StartDate, + ImagePath = program.ProviderImagePath, + ImageUrl = program.ProviderImageUrl, + Name = program.Name, + OfficialRating = program.OfficialRating + }; + } + + var info = await ActiveService.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false); info.Id = null; @@ -1088,7 +1155,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(string programId, CancellationToken cancellationToken) { - var program = GetInternalProgram(programId).ProgramInfo; + var program = GetInternalProgram(programId); var programDto = await GetProgram(programId, cancellationToken).ConfigureAwait(false); var defaults = await GetNewTimerDefaultsInternal(cancellationToken, program).ConfigureAwait(false); @@ -1104,13 +1171,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv info.Name = program.Name; info.ChannelId = programDto.ChannelId; info.ChannelName = programDto.ChannelName; - info.EndDate = program.EndDate; info.StartDate = program.StartDate; info.Name = program.Name; info.Overview = program.Overview; info.ProgramId = programDto.Id; info.ExternalProgramId = programDto.ExternalId; + if (program.EndDate.HasValue) + { + info.EndDate = program.EndDate.Value; + } + return info; } @@ -1299,8 +1370,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var programs = _programs.ToList(); - var startDate = programs.Select(i => i.Value.ProgramInfo.StartDate).Min(); - var endDate = programs.Select(i => i.Value.ProgramInfo.StartDate).Max(); + var startDate = programs.Select(i => i.Value.StartDate).Min(); + var endDate = programs.Select(i => i.Value.StartDate).Max(); return new GuideInfo { @@ -1340,7 +1411,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } - public async Task<IEnumerable<LiveTvServiceInfo>> GetServiceInfos(CancellationToken cancellationToken) + private async Task<IEnumerable<LiveTvServiceInfo>> GetServiceInfos(CancellationToken cancellationToken) { var tasks = Services.Select(i => GetServiceInfo(i, cancellationToken)); @@ -1363,6 +1434,21 @@ namespace MediaBrowser.Server.Implementations.LiveTv info.Version = statusInfo.Version; info.HasUpdateAvailable = statusInfo.HasUpdateAvailable; info.HomePageUrl = service.HomePageUrl; + + info.Tuners = statusInfo.Tuners.Select(i => + { + string channelName = null; + + if (!string.IsNullOrEmpty(i.ChannelId)) + { + var internalChannelId = _tvDtoService.GetInternalChannelId(service.Name, i.ChannelId); + var channel = GetInternalChannel(internalChannelId); + channelName = channel == null ? null : channel.Name; + } + + return _tvDtoService.GetTunerInfoDto(service.Name, i, channelName); + + }).ToList(); } catch (Exception ex) { @@ -1374,5 +1460,41 @@ namespace MediaBrowser.Server.Implementations.LiveTv return info; } + + public async Task<LiveTvInfo> GetLiveTvInfo(CancellationToken cancellationToken) + { + var services = await GetServiceInfos(CancellationToken.None).ConfigureAwait(false); + var servicesList = services.ToList(); + + var activeServiceInfo = ActiveService == null ? null : + servicesList.FirstOrDefault(i => string.Equals(i.Name, ActiveService.Name, StringComparison.OrdinalIgnoreCase)); + + var info = new LiveTvInfo + { + Services = servicesList.ToList(), + ActiveServiceName = activeServiceInfo == null ? null : activeServiceInfo.Name, + IsEnabled = ActiveService != null, + Status = activeServiceInfo == null ? LiveTvServiceStatus.Unavailable : activeServiceInfo.Status, + StatusMessage = activeServiceInfo == null ? null : activeServiceInfo.StatusMessage + }; + + info.EnabledUsers = _userManager.Users + .Where(i => i.Configuration.EnableLiveTvAccess && info.IsEnabled) + .Select(i => i.Id.ToString("N")) + .ToList(); + + return info; + } + + /// <summary> + /// Resets the tuner. + /// </summary> + /// <param name="id">The identifier.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + public Task ResetTuner(string id, CancellationToken cancellationToken) + { + return ActiveService.ResetTuner(id, cancellationToken); + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs index 7c343f77c..041925cdd 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs @@ -76,22 +76,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv private async Task<bool> DownloadImage(LiveTvProgram item, CancellationToken cancellationToken) { - var programInfo = item.ProgramInfo; - Stream imageStream = null; string contentType = null; - if (!string.IsNullOrEmpty(programInfo.ImagePath)) + if (!string.IsNullOrEmpty(item.ProviderImagePath)) { - contentType = "image/" + Path.GetExtension(programInfo.ImagePath).ToLower(); - imageStream = _fileSystem.GetFileStream(programInfo.ImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true); + contentType = "image/" + Path.GetExtension(item.ProviderImagePath).ToLower(); + imageStream = _fileSystem.GetFileStream(item.ProviderImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true); } - else if (!string.IsNullOrEmpty(programInfo.ImageUrl)) + else if (!string.IsNullOrEmpty(item.ProviderImageUrl)) { var options = new HttpRequestOptions { CancellationToken = cancellationToken, - Url = programInfo.ImageUrl + Url = item.ProviderImageUrl }; var response = await _httpClient.GetResponse(options).ConfigureAwait(false); @@ -105,7 +103,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv imageStream = response.Content; contentType = response.ContentType; } - else if (programInfo.HasImage ?? true) + else if (item.HasProviderImage ?? true) { var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, item.ServiceName, StringComparison.OrdinalIgnoreCase)); @@ -113,7 +111,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { try { - var response = await service.GetProgramImageAsync(programInfo.Id, programInfo.ChannelId, cancellationToken).ConfigureAwait(false); + var response = await service.GetProgramImageAsync(item.ExternalId, item.ExternalChannelId, cancellationToken).ConfigureAwait(false); if (response != null) { @@ -131,7 +129,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (imageStream != null) { // Dummy up the original url - var url = item.ServiceName + programInfo.Id; + var url = item.ServiceName + item.ExternalId; await _providerManager.SaveImage(item, imageStream, contentType, ImageType.Primary, null, url, cancellationToken).ConfigureAwait(false); return true; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs index 4463ac6f3..86bf0d71c 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Data; using System.Globalization; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -48,8 +49,8 @@ namespace MediaBrowser.Server.Implementations.Persistence string[] queries = { - "create table if not exists organizationresults (ResultId GUID PRIMARY KEY, OriginalPath TEXT, TargetPath TEXT, OrganizationDate datetime, Status TEXT, OrganizationType TEXT, StatusMessage TEXT, ExtractedName TEXT, ExtractedYear int null, ExtractedSeasonNumber int null, ExtractedEpisodeNumber int null, ExtractedEndingEpisodeNumber int null)", - "create index if not exists idx_organizationresults on organizationresults(ResultId)", + "create table if not exists OrganizerResults (ResultId GUID PRIMARY KEY, OriginalPath TEXT, TargetPath TEXT, OrganizationDate datetime, Status TEXT, OrganizationType TEXT, StatusMessage TEXT, ExtractedName TEXT, ExtractedYear int null, ExtractedSeasonNumber int null, ExtractedEpisodeNumber int null, ExtractedEndingEpisodeNumber, DuplicatePaths TEXT int null)", + "create index if not exists idx_OrganizerResults on OrganizerResults(ResultId)", //pragmas "pragma temp_store = memory", @@ -67,7 +68,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private void PrepareStatements() { _saveResultCommand = _connection.CreateCommand(); - _saveResultCommand.CommandText = "replace into organizationresults (ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber) values (@ResultId, @OriginalPath, @TargetPath, @OrganizationDate, @Status, @OrganizationType, @StatusMessage, @ExtractedName, @ExtractedYear, @ExtractedSeasonNumber, @ExtractedEpisodeNumber, @ExtractedEndingEpisodeNumber)"; + _saveResultCommand.CommandText = "replace into OrganizerResults (ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths) values (@ResultId, @OriginalPath, @TargetPath, @OrganizationDate, @Status, @OrganizationType, @StatusMessage, @ExtractedName, @ExtractedYear, @ExtractedSeasonNumber, @ExtractedEpisodeNumber, @ExtractedEndingEpisodeNumber, @DuplicatePaths)"; _saveResultCommand.Parameters.Add(_saveResultCommand, "@ResultId"); _saveResultCommand.Parameters.Add(_saveResultCommand, "@OriginalPath"); @@ -81,14 +82,15 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedSeasonNumber"); _saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedEpisodeNumber"); _saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedEndingEpisodeNumber"); + _saveResultCommand.Parameters.Add(_saveResultCommand, "@DuplicatePaths"); _deleteResultCommand = _connection.CreateCommand(); - _deleteResultCommand.CommandText = "delete from organizationresults where ResultId = @ResultId"; + _deleteResultCommand.CommandText = "delete from OrganizerResults where ResultId = @ResultId"; _deleteResultCommand.Parameters.Add(_saveResultCommand, "@ResultId"); _deleteAllCommand = _connection.CreateCommand(); - _deleteAllCommand.CommandText = "delete from organizationresults"; + _deleteAllCommand.CommandText = "delete from OrganizerResults"; } public async Task SaveResult(FileOrganizationResult result, CancellationToken cancellationToken) @@ -120,6 +122,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveResultCommand.GetParameter(9).Value = result.ExtractedSeasonNumber; _saveResultCommand.GetParameter(10).Value = result.ExtractedEpisodeNumber; _saveResultCommand.GetParameter(11).Value = result.ExtractedEndingEpisodeNumber; + _saveResultCommand.GetParameter(12).Value = string.Join("|", result.DuplicatePaths.ToArray()); _saveResultCommand.Transaction = transaction; @@ -268,11 +271,11 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = "SELECT ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber from organizationresults"; + cmd.CommandText = "SELECT ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths from OrganizerResults"; if (query.StartIndex.HasValue && query.StartIndex.Value > 0) { - cmd.CommandText += string.Format(" WHERE ResultId NOT IN (SELECT ResultId FROM organizationresults ORDER BY OrganizationDate desc LIMIT {0})", + cmd.CommandText += string.Format(" WHERE ResultId NOT IN (SELECT ResultId FROM OrganizerResults ORDER BY OrganizationDate desc LIMIT {0})", query.StartIndex.Value.ToString(_usCulture)); } @@ -283,7 +286,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); } - cmd.CommandText += "; select count (ResultId) from organizationresults"; + cmd.CommandText += "; select count (ResultId) from OrganizerResults"; var list = new List<FileOrganizationResult>(); var count = 0; @@ -320,7 +323,7 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = "select ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber from organizationresults where ResultId=@Id"; + cmd.CommandText = "select ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths from OrganizerResults where ResultId=@Id"; cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; @@ -389,6 +392,11 @@ namespace MediaBrowser.Server.Implementations.Persistence result.ExtractedEndingEpisodeNumber = reader.GetInt32(11); } + if (!reader.IsDBNull(12)) + { + result.DuplicatePaths = reader.GetString(12).Split('|').Where(i => !string.IsNullOrEmpty(i)).ToList(); + } + return result; } |
