diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs')
| -rw-r--r-- | MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs | 799 |
1 files changed, 546 insertions, 253 deletions
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 185a01663..218c930df 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -8,7 +8,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; @@ -30,29 +29,26 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly IFileSystem _fileSystem; private readonly ILogger _logger; private readonly IItemRepository _itemRepo; - private readonly IImageProcessor _imageProcessor; - private readonly IUserManager _userManager; + private readonly ILocalizationManager _localization; - private readonly IUserDataManager _userDataManager; - private readonly IDtoService _dtoService; + private readonly LiveTvDtoService _tvDtoService; private readonly List<ILiveTvService> _services = new List<ILiveTvService>(); - private List<Channel> _channels = new List<Channel>(); - private List<ProgramInfoDto> _programs = new List<ProgramInfoDto>(); + private Dictionary<Guid, LiveTvChannel> _channels = new Dictionary<Guid, LiveTvChannel>(); + private Dictionary<Guid, LiveTvProgram> _programs = new Dictionary<Guid, LiveTvProgram>(); - public LiveTvManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserManager userManager, ILocalizationManager localization, IUserDataManager userDataManager, IDtoService dtoService) + public LiveTvManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, ILocalizationManager localization, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager) { _appPaths = appPaths; _fileSystem = fileSystem; _logger = logger; _itemRepo = itemRepo; - _imageProcessor = imageProcessor; - _userManager = userManager; _localization = localization; - _userDataManager = userDataManager; - _dtoService = dtoService; + _userManager = userManager; + + _tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger); } /// <summary> @@ -77,77 +73,23 @@ namespace MediaBrowser.Server.Implementations.LiveTv ActiveService = _services.FirstOrDefault(); } - /// <summary> - /// Gets the channel info dto. - /// </summary> - /// <param name="info">The info.</param> - /// <param name="user">The user.</param> - /// <returns>ChannelInfoDto.</returns> - public ChannelInfoDto GetChannelInfoDto(Channel info, User user) - { - var dto = new ChannelInfoDto - { - Name = info.Name, - ServiceName = info.ServiceName, - ChannelType = info.ChannelType, - Number = info.ChannelNumber, - Type = info.GetType().Name, - Id = info.Id.ToString("N"), - MediaType = info.MediaType - }; - - if (user != null) - { - dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, info.GetUserDataKey())); - } - - var imageTag = GetLogoImageTag(info); - - if (imageTag.HasValue) - { - dto.ImageTags[ImageType.Primary] = imageTag.Value; - } - - return dto; - } - - private Guid? GetLogoImageTag(Channel info) - { - var path = info.PrimaryImagePath; - - if (string.IsNullOrEmpty(path)) - { - return null; - } - - try - { - return _imageProcessor.GetImageCacheTag(info, ImageType.Primary, path); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting channel image info for {0}", ex, info.Name); - } - - return null; - } - - public QueryResult<ChannelInfoDto> GetChannels(ChannelQuery query) + public Task<QueryResult<ChannelInfoDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken) { var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId)); - IEnumerable<Channel> channels = _channels; + IEnumerable<LiveTvChannel> channels = _channels.Values; if (user != null) { - channels = channels.Where(i => i.IsParentalAllowed(user, _localization)) + channels = channels + .Where(i => i.IsParentalAllowed(user, _localization)) .OrderBy(i => { double number = 0; - if (!string.IsNullOrEmpty(i.ChannelNumber)) + if (!string.IsNullOrEmpty(i.ChannelInfo.Number)) { - double.TryParse(i.ChannelNumber, out number); + double.TryParse(i.ChannelInfo.Number, out number); } return number; @@ -159,81 +101,81 @@ namespace MediaBrowser.Server.Implementations.LiveTv { double number = 0; - if (!string.IsNullOrEmpty(i.ChannelNumber)) + if (!string.IsNullOrEmpty(i.ChannelInfo.Number)) { - double.TryParse(i.ChannelNumber, out number); + double.TryParse(i.ChannelInfo.Number, out number); } return number; }).ThenBy(i => i.Name) - .Select(i => GetChannelInfoDto(i, user)) + .Select(i => _tvDtoService.GetChannelInfoDto(i, user)) .ToArray(); - return new QueryResult<ChannelInfoDto> + var result = new QueryResult<ChannelInfoDto> { Items = returnChannels, TotalRecordCount = returnChannels.Length }; + + return Task.FromResult(result); } - public Channel GetChannel(string id) + public LiveTvChannel GetInternalChannel(string id) { - var guid = new Guid(id); + return GetInternalChannel(new Guid(id)); + } + + private LiveTvChannel GetInternalChannel(Guid id) + { + LiveTvChannel channel = null; - return _channels.FirstOrDefault(i => i.Id == guid); + _channels.TryGetValue(id, out channel); + return channel; } - public ChannelInfoDto GetChannelInfoDto(string id, string userId) + public LiveTvProgram GetInternalProgram(string id) { - var channel = GetChannel(id); + var guid = new Guid(id); - var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(new Guid(userId)); + LiveTvProgram obj = null; - return channel == null ? null : GetChannelInfoDto(channel, user); + _programs.TryGetValue(guid, out obj); + return obj; } - private ProgramInfoDto GetProgramInfoDto(ProgramInfo program, Channel channel) + public async Task<LiveTvRecording> GetInternalRecording(string id, CancellationToken cancellationToken) { - var id = GetInternalProgramIdId(channel.ServiceName, program.Id).ToString("N"); + var service = ActiveService; - return new ProgramInfoDto - { - ChannelId = channel.Id.ToString("N"), - Overview = program.Overview, - EndDate = program.EndDate, - Genres = program.Genres, - ExternalId = program.Id, - Id = id, - Name = program.Name, - ServiceName = channel.ServiceName, - StartDate = program.StartDate, - OfficialRating = program.OfficialRating, - IsHD = program.IsHD, - OriginalAirDate = program.OriginalAirDate, - Audio = program.Audio, - CommunityRating = program.CommunityRating, - AspectRatio = program.AspectRatio, - IsRepeat = program.IsRepeat, - EpisodeTitle = program.EpisodeTitle - }; + var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false); + + var recording = recordings.FirstOrDefault(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(id)); + + return await GetRecording(recording, service.Name, cancellationToken).ConfigureAwait(false); } - private Guid GetInternalChannelId(string serviceName, string externalChannelId, string channelName) + public async Task<StreamResponseInfo> GetRecordingStream(string id, CancellationToken cancellationToken) { - var name = serviceName + externalChannelId + channelName; + var service = ActiveService; + + var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false); - return name.ToLower().GetMBId(typeof(Channel)); + var recording = recordings.FirstOrDefault(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(id)); + + return await service.GetRecordingStream(recording.Id, cancellationToken).ConfigureAwait(false); } - private Guid GetInternalProgramIdId(string serviceName, string externalProgramId) + public async Task<StreamResponseInfo> GetChannelStream(string id, CancellationToken cancellationToken) { - var name = serviceName + externalProgramId; + var service = ActiveService; + + var channel = GetInternalChannel(id); - return name.ToLower().GetMD5(); + return await service.GetChannelStream(channel.ChannelInfo.Id, cancellationToken).ConfigureAwait(false); } - private async Task<Channel> GetChannel(ChannelInfo channelInfo, string serviceName, CancellationToken cancellationToken) + private async Task<LiveTvChannel> GetChannel(ChannelInfo channelInfo, string serviceName, CancellationToken cancellationToken) { var path = Path.Combine(_appPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(serviceName), _fileSystem.GetValidFilename(channelInfo.Name)); @@ -254,27 +196,27 @@ namespace MediaBrowser.Server.Implementations.LiveTv isNew = true; } - var id = GetInternalChannelId(serviceName, channelInfo.Id, channelInfo.Name); + var id = _tvDtoService.GetInternalChannelId(serviceName, channelInfo.Id); - var item = _itemRepo.RetrieveItem(id) as Channel; + var item = _itemRepo.RetrieveItem(id) as LiveTvChannel; if (item == null) { - item = new Channel + item = new LiveTvChannel { Name = channelInfo.Name, Id = id, DateCreated = _fileSystem.GetCreationTimeUtc(fileInfo), DateModified = _fileSystem.GetLastWriteTimeUtc(fileInfo), - Path = path, - ChannelId = channelInfo.Id, - ChannelNumber = channelInfo.Number, - ServiceName = serviceName + Path = path }; isNew = true; } + item.ChannelInfo = channelInfo; + item.ServiceName = serviceName; + // Set this now so we don't cause additional file system access during provider executions item.ResetResolveArgs(fileInfo); @@ -283,26 +225,160 @@ namespace MediaBrowser.Server.Implementations.LiveTv return item; } + private async Task<LiveTvProgram> GetProgram(ProgramInfo info, ChannelType channelType, string serviceName, CancellationToken cancellationToken) + { + var isNew = false; + + var id = _tvDtoService.GetInternalProgramId(serviceName, info.Id); + + var item = _itemRepo.RetrieveItem(id) as LiveTvProgram; + + if (item == null) + { + item = new LiveTvProgram + { + Name = info.Name, + Id = id, + DateCreated = DateTime.UtcNow, + DateModified = DateTime.UtcNow + }; + + isNew = true; + } + + item.ChannelType = channelType; + item.ProgramInfo = info; + item.ServiceName = serviceName; + + await item.RefreshMetadata(cancellationToken, forceSave: isNew, resetResolveArgs: false); + + return item; + } + + private async Task<LiveTvRecording> GetRecording(RecordingInfo info, string serviceName, CancellationToken cancellationToken) + { + var isNew = false; + + var id = _tvDtoService.GetInternalRecordingId(serviceName, info.Id); + + var item = _itemRepo.RetrieveItem(id) as LiveTvRecording; + + if (item == null) + { + item = new LiveTvRecording + { + Name = info.Name, + Id = id, + DateCreated = DateTime.UtcNow, + DateModified = DateTime.UtcNow + }; + + isNew = true; + } + + item.RecordingInfo = info; + item.ServiceName = serviceName; + + await item.RefreshMetadata(cancellationToken, forceSave: isNew, resetResolveArgs: false); + + return item; + } + + private LiveTvChannel GetChannel(LiveTvProgram program) + { + var programChannelId = program.ProgramInfo.ChannelId; + + var internalProgramChannelId = _tvDtoService.GetInternalChannelId(program.ServiceName, programChannelId); + + return GetInternalChannel(internalProgramChannelId); + } + + public async Task<ProgramInfoDto> GetProgram(string id, CancellationToken cancellationToken, User user = null) + { + var program = GetInternalProgram(id); + + var channel = GetChannel(program); + + var channelName = channel == null ? null : channel.ChannelInfo.Name; + + var dto = _tvDtoService.GetProgramInfoDto(program, channelName, user); + + await AddRecordingInfo(new[] { dto }, cancellationToken).ConfigureAwait(false); + + return dto; + } + public async Task<QueryResult<ProgramInfoDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken) { - IEnumerable<ProgramInfoDto> programs = _programs - .OrderBy(i => i.StartDate) - .ThenBy(i => i.EndDate); + IEnumerable<LiveTvProgram> programs = _programs.Values; if (query.ChannelIdList.Length > 0) { var guids = query.ChannelIdList.Select(i => new Guid(i)).ToList(); + var serviceName = ActiveService.Name; + + programs = programs.Where(i => + { + var programChannelId = i.ProgramInfo.ChannelId; + + var internalProgramChannelId = _tvDtoService.GetInternalChannelId(serviceName, programChannelId); + + return guids.Contains(internalProgramChannelId); + }); + } + + var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId)); - programs = programs.Where(i => guids.Contains(new Guid(i.ChannelId))); + if (user != null) + { + programs = programs.Where(i => i.IsParentalAllowed(user, _localization)); } - var returnArray = programs.ToArray(); + var returnArray = programs + .OrderBy(i => i.ProgramInfo.StartDate) + .Select(i => + { + var channel = GetChannel(i); + + var channelName = channel == null ? null : channel.ChannelInfo.Name; + + return _tvDtoService.GetProgramInfoDto(i, channelName, user); + }) + .ToArray(); + + await AddRecordingInfo(returnArray, cancellationToken).ConfigureAwait(false); - return new QueryResult<ProgramInfoDto> + var result = new QueryResult<ProgramInfoDto> { Items = returnArray, TotalRecordCount = returnArray.Length }; + + return result; + } + + private async Task AddRecordingInfo(IEnumerable<ProgramInfoDto> programs, CancellationToken cancellationToken) + { + var timers = await ActiveService.GetTimersAsync(cancellationToken).ConfigureAwait(false); + var timerList = timers.ToList(); + + foreach (var program in programs) + { + var timer = timerList.FirstOrDefault(i => string.Equals(i.ProgramId, program.ExternalId, StringComparison.OrdinalIgnoreCase)); + + if (timer != null) + { + program.TimerId = _tvDtoService.GetInternalTimerId(program.ServiceName, timer.Id) + .ToString("N"); + + if (!string.IsNullOrEmpty(timer.SeriesTimerId)) + { + program.SeriesTimerId = _tvDtoService.GetInternalSeriesTimerId(program.ServiceName, timer.SeriesTimerId) + .ToString("N"); + } + } + } + } internal async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken) @@ -321,8 +397,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv var allChannels = await GetChannels(service, cancellationToken).ConfigureAwait(false); var allChannelsList = allChannels.ToList(); - var list = new List<Channel>(); - var programs = new List<ProgramInfoDto>(); + var list = new List<LiveTvChannel>(); + var programs = new List<LiveTvProgram>(); var numComplete = 0; @@ -334,7 +410,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv var channelPrograms = await service.GetProgramsAsync(channelInfo.Item2.Id, cancellationToken).ConfigureAwait(false); - programs.AddRange(channelPrograms.Select(program => GetProgramInfoDto(program, item))); + var programTasks = channelPrograms.Select(program => GetProgram(program, item.ChannelInfo.ChannelType, service.Name, cancellationToken)); + var programEntities = await Task.WhenAll(programTasks).ConfigureAwait(false); + + programs.AddRange(programEntities); list.Add(item); } @@ -354,8 +433,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv progress.Report(90 * percent + 10); } - _programs = programs; - _channels = list; + _programs = programs.ToDictionary(i => i.Id); + _channels = list.ToDictionary(i => i.Id); } private async Task<IEnumerable<Tuple<string, ChannelInfo>>> GetChannels(ILiveTvService service, CancellationToken cancellationToken) @@ -365,70 +444,73 @@ namespace MediaBrowser.Server.Implementations.LiveTv return channels.Select(i => new Tuple<string, ChannelInfo>(service.Name, i)); } - private async Task<IEnumerable<RecordingInfoDto>> GetRecordings(ILiveTvService service, CancellationToken cancellationToken) + public async Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken) { + var service = ActiveService; + + var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId)); + + var list = new List<RecordingInfo>(); + var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false); + list.AddRange(recordings); - return recordings.Select(i => GetRecordingInfoDto(i, service)); - } - - private RecordingInfoDto GetRecordingInfoDto(RecordingInfo info, ILiveTvService service) - { - var id = service.Name + info.ChannelId + info.Id; - id = id.GetMD5().ToString("N"); - - var dto = new RecordingInfoDto - { - ChannelName = info.ChannelName, - Overview = info.Overview, - EndDate = info.EndDate, - Name = info.Name, - StartDate = info.StartDate, - Id = id, - ExternalId = info.Id, - ChannelId = GetInternalChannelId(service.Name, info.ChannelId, info.ChannelName).ToString("N"), - Status = info.Status, - Path = info.Path, - Genres = info.Genres, - IsRepeat = info.IsRepeat, - EpisodeTitle = info.EpisodeTitle, - ChannelType = info.ChannelType, - MediaType = info.ChannelType == ChannelType.Radio ? MediaType.Audio : MediaType.Video, - CommunityRating = info.CommunityRating, - OfficialRating = info.OfficialRating, - Audio = info.Audio, - IsHD = info.IsHD - }; + if (!string.IsNullOrEmpty(query.ChannelId)) + { + var guid = new Guid(query.ChannelId); - var duration = info.EndDate - info.StartDate; - dto.DurationMs = Convert.ToInt32(duration.TotalMilliseconds); + var currentServiceName = service.Name; - if (!string.IsNullOrEmpty(info.ProgramId)) + list = list + .Where(i => _tvDtoService.GetInternalChannelId(currentServiceName, i.ChannelId) == guid) + .ToList(); + } + + if (!string.IsNullOrEmpty(query.Id)) { - dto.ProgramId = GetInternalProgramIdId(service.Name, info.ProgramId).ToString("N"); + var guid = new Guid(query.Id); + + var currentServiceName = service.Name; + + list = list + .Where(i => _tvDtoService.GetInternalRecordingId(currentServiceName, i.Id) == guid) + .ToList(); } - return dto; - } + if (!string.IsNullOrEmpty(query.GroupId)) + { + var guid = new Guid(query.GroupId); - public async Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken) - { - var list = new List<RecordingInfoDto>(); + list = list.Where(i => GetRecordingGroupIds(i).Contains(guid)) + .ToList(); + } + + IEnumerable<LiveTvRecording> entities = await GetEntities(list, service.Name, cancellationToken).ConfigureAwait(false); + + entities = entities.OrderByDescending(i => i.RecordingInfo.StartDate); - if (ActiveService != null) + if (user != null) { - var recordings = await GetRecordings(ActiveService, cancellationToken).ConfigureAwait(false); + var currentUser = user; + entities = entities.Where(i => i.IsParentalAllowed(currentUser, _localization)); + } - list.AddRange(recordings); + if (query.StartIndex.HasValue) + { + entities = entities.Skip(query.StartIndex.Value); } - if (!string.IsNullOrEmpty(query.ChannelId)) + if (query.Limit.HasValue) { - list = list.Where(i => string.Equals(i.ChannelId, query.ChannelId)) - .ToList(); + entities = entities.Take(query.Limit.Value); } - var returnArray = list.OrderByDescending(i => i.StartDate) + var returnArray = entities + .Select(i => + { + var channel = string.IsNullOrEmpty(i.RecordingInfo.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, i.RecordingInfo.ChannelId)); + return _tvDtoService.GetRecordingInfoDto(i, channel, service, user); + }) .ToArray(); return new QueryResult<RecordingInfoDto> @@ -438,17 +520,25 @@ namespace MediaBrowser.Server.Implementations.LiveTv }; } + private Task<LiveTvRecording[]> GetEntities(IEnumerable<RecordingInfo> recordings, string serviceName, CancellationToken cancellationToken) + { + var tasks = recordings.Select(i => GetRecording(i, serviceName, cancellationToken)); + + return Task.WhenAll(tasks); + } + private IEnumerable<ILiveTvService> GetServices(string serviceName, string channelId) { IEnumerable<ILiveTvService> services = _services; if (string.IsNullOrEmpty(serviceName) && !string.IsNullOrEmpty(channelId)) { - var channelIdGuid = new Guid(channelId); + var channel = GetInternalChannel(channelId); - serviceName = _channels.Where(i => i.Id == channelIdGuid) - .Select(i => i.ServiceName) - .FirstOrDefault(); + if (channel != null) + { + serviceName = channel.ServiceName; + } } if (!string.IsNullOrEmpty(serviceName)) @@ -459,137 +549,340 @@ namespace MediaBrowser.Server.Implementations.LiveTv return services; } - public Task ScheduleRecording(string programId) + public async Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, CancellationToken cancellationToken) { - throw new NotImplementedException(); + var service = ActiveService; + var timers = await service.GetTimersAsync(cancellationToken).ConfigureAwait(false); + + if (!string.IsNullOrEmpty(query.ChannelId)) + { + var guid = new Guid(query.ChannelId); + timers = timers.Where(i => guid == _tvDtoService.GetInternalChannelId(service.Name, i.ChannelId)); + } + + var returnArray = timers + .Select(i => + { + var program = string.IsNullOrEmpty(i.ProgramId) ? null : GetInternalProgram(_tvDtoService.GetInternalProgramId(service.Name, i.ProgramId).ToString("N")); + var channel = string.IsNullOrEmpty(i.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, i.ChannelId)); + + return _tvDtoService.GetTimerInfoDto(i, service, program, channel); + }) + .OrderBy(i => i.StartDate) + .ToArray(); + + return new QueryResult<TimerInfoDto> + { + Items = returnArray, + TotalRecordCount = returnArray.Length + }; } - public async Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, CancellationToken cancellationToken) + public async Task DeleteRecording(string recordingId) { - var list = new List<TimerInfoDto>(); + var recording = await GetRecording(recordingId, CancellationToken.None).ConfigureAwait(false); - if (ActiveService != null) + if (recording == null) { - var timers = await GetTimers(ActiveService, cancellationToken).ConfigureAwait(false); + throw new ResourceNotFoundException(string.Format("Recording with Id {0} not found", recordingId)); + } + + var service = GetServices(recording.ServiceName, null) + .First(); + + await service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None).ConfigureAwait(false); + } + + public async Task CancelTimer(string id) + { + var timer = await GetTimer(id, CancellationToken.None).ConfigureAwait(false); - list.AddRange(timers); + if (timer == null) + { + throw new ResourceNotFoundException(string.Format("Timer with Id {0} not found", id)); } - if (!string.IsNullOrEmpty(query.ChannelId)) + var service = GetServices(timer.ServiceName, null) + .First(); + + await service.CancelTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false); + } + + public async Task CancelSeriesTimer(string id) + { + var timer = await GetSeriesTimer(id, CancellationToken.None).ConfigureAwait(false); + + if (timer == null) { - list = list.Where(i => string.Equals(i.ChannelId, query.ChannelId)) - .ToList(); + throw new ResourceNotFoundException(string.Format("Timer with Id {0} not found", id)); } - var returnArray = list.OrderByDescending(i => i.StartDate) + var service = GetServices(timer.ServiceName, null) + .First(); + + await service.CancelSeriesTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false); + } + + public async Task<RecordingInfoDto> GetRecording(string id, CancellationToken cancellationToken, User user = null) + { + var results = await GetRecordings(new RecordingQuery + { + UserId = user == null ? null : user.Id.ToString("N"), + Id = id + + }, cancellationToken).ConfigureAwait(false); + + return results.Items.FirstOrDefault(); + } + + public async Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken) + { + var results = await GetTimers(new TimerQuery(), cancellationToken).ConfigureAwait(false); + + return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.CurrentCulture)); + } + + public async Task<SeriesTimerInfoDto> GetSeriesTimer(string id, CancellationToken cancellationToken) + { + var results = await GetSeriesTimers(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false); + + return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.CurrentCulture)); + } + + public async Task<QueryResult<SeriesTimerInfoDto>> GetSeriesTimers(SeriesTimerQuery query, CancellationToken cancellationToken) + { + var service = ActiveService; + + var timers = await service.GetSeriesTimersAsync(cancellationToken).ConfigureAwait(false); + + var returnArray = timers + .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.ChannelInfo.Name; + } + + return _tvDtoService.GetSeriesTimerInfoDto(i, service, channelName); + + }) + .OrderByDescending(i => i.StartDate) .ToArray(); - return new QueryResult<TimerInfoDto> + return new QueryResult<SeriesTimerInfoDto> { Items = returnArray, TotalRecordCount = returnArray.Length }; } - private async Task<IEnumerable<TimerInfoDto>> GetTimers(ILiveTvService service, CancellationToken cancellationToken) + public Task<ChannelInfoDto> GetChannel(string id, CancellationToken cancellationToken, User user = null) { - var timers = await service.GetTimersAsync(cancellationToken).ConfigureAwait(false); + var channel = GetInternalChannel(id); + + var dto = _tvDtoService.GetChannelInfoDto(channel, user); - return timers.Select(i => GetTimerInfoDto(i, service)); + return Task.FromResult(dto); } - private TimerInfoDto GetTimerInfoDto(TimerInfo info, ILiveTvService service) + public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(CancellationToken cancellationToken) { - var id = service.Name + info.ChannelId + info.Id; - id = id.GetMD5().ToString("N"); + var service = ActiveService; + + var info = await service.GetNewTimerDefaultsAsync(cancellationToken).ConfigureAwait(false); + + var obj = _tvDtoService.GetSeriesTimerInfoDto(info, service, null); + + obj.Id = obj.ExternalId = string.Empty; + + return obj; + } - var dto = new TimerInfoDto + public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(string programId, CancellationToken cancellationToken) + { + var info = await GetNewTimerDefaults(cancellationToken).ConfigureAwait(false); + + var program = await GetProgram(programId, cancellationToken).ConfigureAwait(false); + + info.Days = new List<DayOfWeek> { - ChannelName = info.ChannelName, - Description = info.Description, - EndDate = info.EndDate, - Name = info.Name, - StartDate = info.StartDate, - Id = id, - ExternalId = info.Id, - ChannelId = GetInternalChannelId(service.Name, info.ChannelId, info.ChannelName).ToString("N"), - Status = info.Status, - SeriesTimerId = info.SeriesTimerId, - RequestedPostPaddingSeconds = info.RequestedPostPaddingSeconds, - RequestedPrePaddingSeconds = info.RequestedPrePaddingSeconds, - RequiredPostPaddingSeconds = info.RequiredPostPaddingSeconds, - RequiredPrePaddingSeconds = info.RequiredPrePaddingSeconds + program.StartDate.ToLocalTime().DayOfWeek }; - var duration = info.EndDate - info.StartDate; - dto.DurationMs = Convert.ToInt32(duration.TotalMilliseconds); + info.DayPattern = _tvDtoService.GetDayPattern(info.Days); - if (!string.IsNullOrEmpty(info.ProgramId)) - { - dto.ProgramId = GetInternalProgramIdId(service.Name, info.ProgramId).ToString("N"); - } + info.Name = program.Name; + info.ChannelId = program.ChannelId; + info.ChannelName = program.ChannelName; + info.EndDate = program.EndDate; + info.StartDate = program.StartDate; + info.Name = program.Name; + info.Overview = program.Overview; + info.ProgramId = program.Id; + info.ExternalProgramId = program.ExternalId; - return dto; + return info; } - public async Task DeleteRecording(string recordingId) + public async Task CreateTimer(TimerInfoDto timer, CancellationToken cancellationToken) { - var recordings = await GetRecordings(new RecordingQuery - { + var service = string.IsNullOrEmpty(timer.ServiceName) ? ActiveService : GetServices(timer.ServiceName, null).First(); - }, CancellationToken.None).ConfigureAwait(false); + var info = await _tvDtoService.GetTimerInfo(timer, true, this, cancellationToken).ConfigureAwait(false); - var recording = recordings.Items - .FirstOrDefault(i => string.Equals(recordingId, i.Id, StringComparison.OrdinalIgnoreCase)); + // Set priority from default values + var defaultValues = await service.GetNewTimerDefaultsAsync(cancellationToken).ConfigureAwait(false); + info.Priority = defaultValues.Priority; - if (recording == null) - { - throw new ResourceNotFoundException(string.Format("Recording with Id {0} not found", recordingId)); - } + await service.CreateTimerAsync(info, cancellationToken).ConfigureAwait(false); + } - var channel = GetChannel(recording.ChannelId); + public async Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken) + { + var service = string.IsNullOrEmpty(timer.ServiceName) ? ActiveService : GetServices(timer.ServiceName, null).First(); - var service = GetServices(channel.ServiceName, null) - .First(); + var info = await _tvDtoService.GetSeriesTimerInfo(timer, true, this, cancellationToken).ConfigureAwait(false); - await service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None).ConfigureAwait(false); + // Set priority from default values + var defaultValues = await service.GetNewTimerDefaultsAsync(cancellationToken).ConfigureAwait(false); + info.Priority = defaultValues.Priority; + + await service.CreateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false); } - public async Task CancelTimer(string id) + public async Task UpdateTimer(TimerInfoDto timer, CancellationToken cancellationToken) + { + var info = await _tvDtoService.GetTimerInfo(timer, false, this, cancellationToken).ConfigureAwait(false); + + var service = string.IsNullOrEmpty(timer.ServiceName) ? ActiveService : GetServices(timer.ServiceName, null).First(); + + await service.UpdateTimerAsync(info, cancellationToken).ConfigureAwait(false); + } + + public async Task UpdateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken) + { + var info = await _tvDtoService.GetSeriesTimerInfo(timer, false, this, cancellationToken).ConfigureAwait(false); + + var service = string.IsNullOrEmpty(timer.ServiceName) ? ActiveService : GetServices(timer.ServiceName, null).First(); + + await service.UpdateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false); + } + + private List<string> GetRecordingGroupNames(RecordingInfo recording) { - var timers = await GetTimers(new TimerQuery + var list = new List<string>(); + + if (recording.IsSeries) { + list.Add(recording.Name); + } - }, CancellationToken.None).ConfigureAwait(false); + if (recording.IsKids) + { + list.Add("Kids"); + } - var timer = timers.Items - .FirstOrDefault(i => string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase)); + if (recording.IsMovie) + { + list.Add("Movies"); + } - if (timer == null) + if (recording.IsNews) { - throw new ResourceNotFoundException(string.Format("Timer with Id {0} not found", id)); + list.Add("News"); } - var channel = GetChannel(timer.ChannelId); + if (recording.IsPremiere) + { + list.Add("Sports"); + } - var service = GetServices(channel.ServiceName, null) - .First(); + if (!recording.IsSports && !recording.IsNews && !recording.IsMovie && !recording.IsKids && !recording.IsSeries) + { + list.Add("Others"); + } - await service.CancelTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false); + return list; } - public async Task<RecordingInfoDto> GetRecording(string id, CancellationToken cancellationToken) + private List<Guid> GetRecordingGroupIds(RecordingInfo recording) { - var results = await GetRecordings(new RecordingQuery(), cancellationToken).ConfigureAwait(false); - - return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.CurrentCulture)); + return GetRecordingGroupNames(recording).Select(i => i.ToLower() + .GetMD5()) + .ToList(); } - public async Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken) + public async Task<QueryResult<RecordingGroupDto>> GetRecordingGroups(RecordingGroupQuery query, CancellationToken cancellationToken) { - var results = await GetTimers(new TimerQuery(), cancellationToken).ConfigureAwait(false); + var recordingResult = await GetRecordings(new RecordingQuery + { + UserId = query.UserId - return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.CurrentCulture)); + }, cancellationToken).ConfigureAwait(false); + + var recordings = recordingResult.Items; + + var groups = new List<RecordingGroupDto>(); + + var series = recordings + .Where(i => i.IsSeries) + .ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase) + .ToList(); + + groups.AddRange(series.OrderBy(i => i.Key).Select(i => new RecordingGroupDto + { + Name = i.Key, + RecordingCount = i.Count() + })); + + groups.Add(new RecordingGroupDto + { + Name = "Kids", + RecordingCount = recordings.Count(i => i.IsKids) + }); + + groups.Add(new RecordingGroupDto + { + Name = "Movies", + RecordingCount = recordings.Count(i => i.IsMovie) + }); + + groups.Add(new RecordingGroupDto + { + Name = "News", + RecordingCount = recordings.Count(i => i.IsNews) + }); + + groups.Add(new RecordingGroupDto + { + Name = "Sports", + RecordingCount = recordings.Count(i => i.IsSports) + }); + + groups.Add(new RecordingGroupDto + { + Name = "Others", + RecordingCount = recordings.Count(i => !i.IsSports && !i.IsNews && !i.IsMovie && !i.IsKids && !i.IsSeries) + }); + + groups = groups + .Where(i => i.RecordingCount > 0) + .ToList(); + + foreach (var group in groups) + { + group.Id = group.Name.ToLower().GetMD5().ToString("N"); + } + + return new QueryResult<RecordingGroupDto> + { + Items = groups.ToArray(), + TotalRecordCount = groups.Count + }; } } } |
