public async Task <IEnumerable <RecordingInfo> > GetRecordingsAsync(CancellationToken cancellationToken) { var recordings = _recordingProvider.GetAll().ToList(); var updated = false; foreach (var recording in recordings) { if (recording.Status == RecordingStatus.InProgress) { if (string.IsNullOrWhiteSpace(recording.TimerId) || !_activeRecordings.ContainsKey(recording.TimerId)) { recording.Status = RecordingStatus.Cancelled; recording.DateLastUpdated = DateTime.UtcNow; _recordingProvider.Update(recording); updated = true; } } } if (updated) { recordings = _recordingProvider.GetAll().ToList(); } return(recordings); }
public async Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken) { _seriesTimerProvider.Update(info); List <ProgramInfo> epgData; if (info.RecordAnyChannel) { var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false); var channelIds = channels.Select(i => i.Id).ToList(); epgData = GetEpgDataForChannels(channelIds); } else { epgData = GetEpgDataForChannel(info.ChannelId); } await UpdateTimersForSeriesTimer(epgData, info).ConfigureAwait(false); }
public async Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken) { var instance = _seriesTimerProvider.GetAll().FirstOrDefault(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); if (instance != null) { instance.ChannelId = info.ChannelId; instance.Days = info.Days; instance.EndDate = info.EndDate; instance.IsPostPaddingRequired = info.IsPostPaddingRequired; instance.IsPrePaddingRequired = info.IsPrePaddingRequired; instance.PostPaddingSeconds = info.PostPaddingSeconds; instance.PrePaddingSeconds = info.PrePaddingSeconds; instance.Priority = info.Priority; instance.RecordAnyChannel = info.RecordAnyChannel; instance.RecordAnyTime = info.RecordAnyTime; instance.RecordNewOnly = info.RecordNewOnly; instance.StartDate = info.StartDate; _seriesTimerProvider.Update(instance); List <ProgramInfo> epgData; if (instance.RecordAnyChannel) { var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false); var channelIds = channels.Select(i => i.Id).ToList(); epgData = GetEpgDataForChannels(channelIds); } else { epgData = GetEpgDataForChannel(instance.ChannelId); } await UpdateTimersForSeriesTimer(epgData, instance, true).ConfigureAwait(false); } }
private async Task RecordStream(TimerInfo timer, CancellationToken cancellationToken) { if (timer == null) { throw new ArgumentNullException("timer"); } var mediaStreamInfo = await GetChannelStream(timer.ChannelId, null, CancellationToken.None); var duration = (timer.EndDate - DateTime.UtcNow).Add(TimeSpan.FromSeconds(timer.PostPaddingSeconds)); HttpRequestOptions httpRequestOptions = new HttpRequestOptions() { Url = mediaStreamInfo.Path }; var info = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId); var recordPath = RecordingPath; if (info.IsMovie) { recordPath = Path.Combine(recordPath, "Movies", _fileSystem.GetValidFilename(info.Name)); } else if (info.IsSeries) { recordPath = Path.Combine(recordPath, "Series", _fileSystem.GetValidFilename(info.Name)); } else if (info.IsKids) { recordPath = Path.Combine(recordPath, "Kids", _fileSystem.GetValidFilename(info.Name)); } else if (info.IsSports) { recordPath = Path.Combine(recordPath, "Sports", _fileSystem.GetValidFilename(info.Name)); } else { recordPath = Path.Combine(recordPath, "Other", _fileSystem.GetValidFilename(info.Name)); } var recordingFileName = _fileSystem.GetValidFilename(RecordingHelper.GetRecordingName(timer, info)) + ".ts"; recordPath = Path.Combine(recordPath, recordingFileName); Directory.CreateDirectory(Path.GetDirectoryName(recordPath)); var recording = _recordingProvider.GetAll().FirstOrDefault(x => string.Equals(x.ProgramId, info.Id, StringComparison.OrdinalIgnoreCase)); if (recording == null) { recording = new RecordingInfo { ChannelId = info.ChannelId, Id = Guid.NewGuid().ToString("N"), StartDate = info.StartDate, EndDate = info.EndDate, Genres = info.Genres, IsKids = info.IsKids, IsLive = info.IsLive, IsMovie = info.IsMovie, IsHD = info.IsHD, IsNews = info.IsNews, IsPremiere = info.IsPremiere, IsSeries = info.IsSeries, IsSports = info.IsSports, IsRepeat = !info.IsPremiere, Name = info.Name, EpisodeTitle = info.EpisodeTitle, ProgramId = info.Id, HasImage = info.HasImage, ImagePath = info.ImagePath, ImageUrl = info.ImageUrl, OriginalAirDate = info.OriginalAirDate, Status = RecordingStatus.Scheduled, Overview = info.Overview, SeriesTimerId = timer.SeriesTimerId, TimerId = timer.Id, ShowId = info.ShowId }; _recordingProvider.Add(recording); } recording.Path = recordPath; recording.Status = RecordingStatus.InProgress; recording.DateLastUpdated = DateTime.UtcNow; _recordingProvider.Update(recording); _logger.Info("Beginning recording."); try { httpRequestOptions.BufferContent = false; var durationToken = new CancellationTokenSource(duration); var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; httpRequestOptions.CancellationToken = linkedToken; _logger.Info("Writing file to path: " + recordPath); using (var response = await _httpClient.SendAsync(httpRequestOptions, "GET")) { using (var output = File.Open(recordPath, FileMode.Create, FileAccess.Write, FileShare.Read)) { await response.Content.CopyToAsync(output, StreamDefaults.DefaultCopyToBufferSize, linkedToken); } } recording.Status = RecordingStatus.Completed; _logger.Info("Recording completed"); } catch (OperationCanceledException) { _logger.Info("Recording stopped"); recording.Status = RecordingStatus.Completed; } catch (Exception ex) { _logger.ErrorException("Error recording", ex); recording.Status = RecordingStatus.Error; } finally { CancellationTokenSource removed; _activeRecordings.TryRemove(timer.Id, out removed); } recording.DateLastUpdated = DateTime.UtcNow; _recordingProvider.Update(recording); if (recording.Status == RecordingStatus.Completed) { OnSuccessfulRecording(recording); _timerProvider.Delete(timer); } else if (DateTime.UtcNow < timer.EndDate) { const int retryIntervalSeconds = 60; _logger.Info("Retrying recording in {0} seconds.", retryIntervalSeconds); _timerProvider.StartTimer(timer, TimeSpan.FromSeconds(retryIntervalSeconds)); } else { _timerProvider.Delete(timer); _recordingProvider.Delete(recording); } }