/// <summary> /// Update a single Timer /// </summary> /// <param name="info">The program info</param> /// <param name="cancellationToken">The CancellationToken</param> /// <returns></returns> public async Task UpdateTimerAsync(TimerInfo info, CancellationToken cancellationToken) { _logger.Info(string.Format("[MythTV] Start UpdateTimer Async for ChannelId: {0} & Name: {1}", info.ChannelId, info.Name)); EnsureSetup(); using (var stream = await _httpClient.Get(GetOptions(cancellationToken, "/Dvr/GetRecordSchedule?RecordId={0}", info.Id)).ConfigureAwait(false)) { RecRule orgRule = DvrResponse.GetRecRule(stream, _jsonSerializer, _logger); if (orgRule != null) { orgRule.Title = info.Name; orgRule.ChanId = info.ChannelId; orgRule.CallSign = await GetCallsign(info.ChannelId, cancellationToken); orgRule.EndTime = info.EndDate; orgRule.StartTime = info.StartDate; orgRule.StartOffset = info.PrePaddingSeconds / 60; orgRule.EndOffset = info.PostPaddingSeconds / 60; var options = PostOptions(cancellationToken, ConvertJsonRecRuleToPost(_jsonSerializer.SerializeToString(orgRule)), "/Dvr/UpdateRecordSchedule"); using (var response = await _httpClient.Post(options).ConfigureAwait(false)) { } } } }
/// <summary> /// Create a new recording /// </summary> /// <param name="info">The TimerInfo</param> /// <param name="cancellationToken">The cancellationToken</param> /// <returns></returns> public async Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken) { var timerJson = _jsonSerializer.SerializeToString(info); _logger.Info($"[MythTV] Start CreateTimer Async for TimerInfo\n{timerJson}"); await EnsureSetup(); var options = GetRuleStreamOptions(info.ProgramId, info.StartDate, cancellationToken); using (var stream = await _httpClient.Get(options)) { try { var json = new DvrResponse().GetNewTimerJson(info, stream, _jsonSerializer, _logger); var post = PostOptions(cancellationToken, ConvertJsonRecRuleToPost(json), "/Dvr/AddRecordSchedule"); await _httpClient.Post(post).ConfigureAwait(false); } catch (ExistingTimerException existing) { _logger.Info($"[MythTV] found existing rule {existing.id}"); await CancelTimerAsync(existing.id, cancellationToken); } } }
public async Task <SeriesTimerInfo> GetNewTimerDefaultsAsync(CancellationToken cancellationToken, ProgramInfo program = null) { _logger.Info("[MythTV] Start GetNewTimerDefault Async"); EnsureSetup(); using (var stream = await _httpClient.Get(GetOptions(cancellationToken, "/Dvr/GetRecordSchedule?Template=Default")).ConfigureAwait(false)) { return(DvrResponse.GetDefaultTimerInfo(stream, _jsonSerializer, _logger)); } }
/// <summary> /// Get the recurrent recordings /// </summary> /// <param name="cancellationToken">The CancellationToken</param> /// <returns></returns> public async Task <IEnumerable <SeriesTimerInfo> > GetSeriesTimersAsync(CancellationToken cancellationToken) { _logger.Info("[MythTV] Start GetSeriesTimer Async, retrieve the recurring recordings"); EnsureSetup(); using (var stream = await _httpClient.Get(GetOptions(cancellationToken, "/Dvr/GetRecordScheduleList")).ConfigureAwait(false)) { return(DvrResponse.GetSeriesTimers(stream, _jsonSerializer, _logger)); } }
/// <summary> /// Create a recurrent recording /// </summary> /// <param name="info">The recurrend program info</param> /// <param name="cancellationToken">The CancelationToken</param> /// <returns></returns> public async Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken) { _logger.Info(string.Format("[MythTV] Start CreateSeriesTimer Async for ChannelId: {0} & Name: {1}", info.ChannelId, info.Name)); EnsureSetup(); using (var stream = await _httpClient.Get(GetOptions(cancellationToken, "/Dvr/GetRecordSchedule?Template=Default")).ConfigureAwait(false)) { RecRule orgRule = DvrResponse.GetRecRule(stream, _jsonSerializer, _logger); if (orgRule != null) { orgRule.Title = info.Name; orgRule.ChanId = info.ChannelId; orgRule.CallSign = await GetCallsign(info.ChannelId, cancellationToken); orgRule.EndTime = info.EndDate; orgRule.StartTime = info.StartDate; orgRule.StartOffset = info.PrePaddingSeconds / 60; orgRule.EndOffset = info.PostPaddingSeconds / 60; orgRule.Type = "Record All"; //orgRule.FindDay if (info.RecordAnyChannel) { orgRule.Filter |= RecFilter.ThisChannel; } else { orgRule.Filter &= RecFilter.ThisChannel; } if (info.RecordAnyTime) { orgRule.Filter &= RecFilter.ThisDayTime; } else { orgRule.Filter |= RecFilter.ThisDayTime; } if (info.RecordNewOnly) { orgRule.Filter |= RecFilter.NewEpisode; } else { orgRule.Filter &= RecFilter.NewEpisode; } var options = PostOptions(cancellationToken, ConvertJsonRecRuleToPost(_jsonSerializer.SerializeToString(orgRule)), "/Dvr/AddRecordSchedule"); using (var response = await _httpClient.Post(options).ConfigureAwait(false)) { } } } }
/// <summary> /// Update the series Timer /// </summary> /// <param name="info">The series program info</param> /// <param name="cancellationToken">The CancellationToken</param> /// <returns></returns> public async Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken) { var seriesTimerJson = _jsonSerializer.SerializeToString(info); _logger.Info($"[MythTV] Start UpdateSeriesTimer Async for SeriesTimerInfo\n{seriesTimerJson}"); await EnsureSetup(); var options = GetRuleStreamOptions(info.Id, cancellationToken); using (var stream = await _httpClient.Get(options)) { var json = new DvrResponse().GetNewSeriesTimerJson(info, stream, _jsonSerializer, _logger); var post = PostOptions(cancellationToken, ConvertJsonRecRuleToPost(json), "/Dvr/UpdateRecordSchedule"); await _httpClient.Post(post).ConfigureAwait(false); } }
/// <summary> /// Gets the Recordings async /// </summary> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{IEnumerable{RecordingInfo}}</returns> public async Task <IEnumerable <RecordingInfo> > GetRecordingsAsync(CancellationToken cancellationToken) { _logger.Info("[MythTV] Start GetRecordings Async, retrieve all 'Pending', 'Inprogress' and 'Completed' recordings "); await EnsureSetup(); IEnumerable <RecordingInfo> outp; using (var stream = await _httpClient.Get(GetOptions(cancellationToken, "/Dvr/GetRecordedList")).ConfigureAwait(false)) { outp = new DvrResponse(Plugin.Instance.Configuration.StorageGroupMaps).GetRecordings(stream, _jsonSerializer, _logger, _fileSystem).ToList(); } if (_imageGrabber != null) { await _imageGrabber.AddImages(outp, cancellationToken); } return(outp); }
public async Task <LiveTvServiceStatusInfo> GetStatusInfoAsync(CancellationToken cancellationToken) { EnsureSetup(); bool upgradeAvailable = false; string serverVersion = string.Empty; var conInfoTask = _httpClient.Get(GetOptions(cancellationToken, "/Myth/GetConnectionInfo")).ConfigureAwait(false); var tunersTask = _httpClient.Get(GetOptions(cancellationToken, "/Dvr/GetEncoderList")).ConfigureAwait(false); var encodersTask = _httpClient.Get(GetOptions(cancellationToken, "/Capture/GetCaptureCardList")).ConfigureAwait(false); EncoderList tuners = null; CaptureCardList encoders = null; using (var stream = await tunersTask) { tuners = DvrResponse.ParseEncoderList(stream, _jsonSerializer, _logger); } using (var stream = await encodersTask) { encoders = CaptureResponse.ParseCaptureCardList(stream, _jsonSerializer, _logger); } using (var stream = await conInfoTask) { var conInfo = UtilityResponse.GetConnectionInfo(stream, _jsonSerializer, _logger); serverVersion = conInfo.Version.Ver; } //Tuner information List <LiveTvTunerInfo> tvTunerInfos = new List <LiveTvTunerInfo>(); foreach (var tuner in tuners.Encoders) { LiveTvTunerInfo info = new LiveTvTunerInfo() { Id = tuner.Id.ToString(), Status = (LiveTvTunerStatus)tuner.State }; switch (tuner.State) { case 0: info.Status = LiveTvTunerStatus.Available; break; case 7: info.Status = LiveTvTunerStatus.RecordingTv; break; } if (!string.IsNullOrWhiteSpace(tuner.Recording.Title)) { info.RecordingId = tuner.Recording.ProgramId; info.ProgramName = string.Format("{0} : {1}", tuner.Recording.Title, tuner.Recording.SubTitle); } foreach (var enc in encoders.CaptureCards) { if (enc.CardId == tuner.Id) { info.Name = string.Format("{0} {1}", enc.CardType, enc.VideoDevice); info.SourceType = enc.CardType; break; } } tvTunerInfos.Add(info); } return(new LiveTvServiceStatusInfo { HasUpdateAvailable = upgradeAvailable, Version = serverVersion, Tuners = tvTunerInfos }); }
public async Task <MediaSourceInfo> GetChannelStream(string channelOid, string mediaSourceId, CancellationToken cancellationToken) { _logger.Info("[MythTV] Start ChannelStream"); throw new NotImplementedException(); using (var stream = await _httpClient.Get(GetOptions(cancellationToken, "/Dvr/GetRecordSchedule?Template=Default")).ConfigureAwait(false)) { RecRule orgRule = DvrResponse.GetRecRule(stream, _jsonSerializer, _logger); if (orgRule != null) { DateTime startTime = DateTime.Now.ToUniversalTime(); orgRule.Title = string.Format("Emby LiveTV: {0} ({1}) - {1}", await GetCallsign(channelOid, cancellationToken), channelOid, startTime); orgRule.ChanId = channelOid; orgRule.CallSign = await GetCallsign(channelOid, cancellationToken); orgRule.EndTime = startTime.AddHours(5); orgRule.StartTime = startTime; orgRule.StartOffset = 0; orgRule.EndOffset = 0; orgRule.Type = "Single Record"; var postContent = ConvertJsonRecRuleToPost(_jsonSerializer.SerializeToString(orgRule)); var options = PostOptions(cancellationToken, postContent, "/Dvr/AddRecordSchedule"); using (var response = await _httpClient.Post(options).ConfigureAwait(false)) { RecordId recId = DvrResponse.ParseRecordId(response.Content, _jsonSerializer); for (int i = 0; i < Plugin.Instance.Configuration.LiveTvWaits; i++) { await Task.Delay(200).ConfigureAwait(false); try { using (var rpstream = await _httpClient.Get(GetOptions(cancellationToken, "/Dvr/GetRecorded?ChanId={0}&StartTime={1}", channelOid, FormateMythDate(startTime))).ConfigureAwait(false)) { var recProg = DvrResponse.ParseRecorded(rpstream, _jsonSerializer, _logger);//Host.DvrService.GetRecorded(int.Parse(channelOid), startTime); if (recProg != null && File.Exists(Path.Combine(Plugin.Instance.Configuration.UncPath, recProg.FileName))) { return(new MediaSourceInfo { Id = [email protected](CultureInfo.InvariantCulture), Path = Path.Combine(Plugin.Instance.Configuration.UncPath, recProg.FileName), Protocol = MediaProtocol.File, MediaStreams = new List <MediaStream> { new MediaStream { Type = MediaStreamType.Video, // Set the index to -1 because we don't know the exact index of the video stream within the container Index = -1 }, new MediaStream { Type = MediaStreamType.Audio, // Set the index to -1 because we don't know the exact index of the audio stream within the container Index = -1 } } }); break; } } } catch { _logger.Info("GetChannelStream wait {0} for {1}", i, channelOid); } } } } throw new ResourceNotFoundException(string.Format("Could not stream channel {0}", channelOid)); } }
/// <summary> /// Gets the Recordings async /// </summary> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{IEnumerable{RecordingInfo}}</returns> public async Task <IEnumerable <RecordingInfo> > GetRecordingsAsync(CancellationToken cancellationToken) { List <RecordingInfo> ret = new List <RecordingInfo>(); _logger.Info("[MythTV] Start GetRecordings Async, retrieve all 'Pending', 'Inprogress' and 'Completed' recordings "); EnsureSetup(); using (var stream = await _httpClient.Get(GetOptions(cancellationToken, "/Dvr/GetRecordedList")).ConfigureAwait(false)) { var recordings = DvrResponse.ParseProgramList(stream, _jsonSerializer, _logger); foreach (var item in recordings.Programs) { if (!Plugin.Instance.RecGroupExclude.Contains(item.Recording.RecGroup)) { RecordingInfo val = new RecordingInfo() { Name = item.Title, EpisodeTitle = item.SubTitle, Overview = item.Description, Audio = ProgramAudio.Stereo, //Hardcode for now (ProgramAudio)item.AudioProps, ChannelId = item.Channel.ChanId.ToString(), ProgramId = item.ProgramId, SeriesTimerId = item.Recording.RecordId.ToString(), EndDate = (DateTime)item.EndTime, StartDate = (DateTime)item.StartTime, Url = string.Format("{0}{1}", Plugin.Instance.Configuration.WebServiceUrl, string.Format("/Content/GetFile?StorageGroup={0}&FileName={1}", item.Recording.StorageGroup, item.FileName)), Id = string.Format("StartTime={0}&ChanId={1}", ((DateTime)item.StartTime).Ticks, item.Channel.ChanId), IsSeries = GeneralHelpers.ContainsWord(item.CatType, "series", StringComparison.OrdinalIgnoreCase), IsMovie = GeneralHelpers.ContainsWord(item.CatType, "movie", StringComparison.OrdinalIgnoreCase), IsRepeat = item.Repeat, IsNews = GeneralHelpers.ContainsWord(item.Category, "news", StringComparison.OrdinalIgnoreCase), IsKids = GeneralHelpers.ContainsWord(item.Category, "animation", StringComparison.OrdinalIgnoreCase), IsSports = GeneralHelpers.ContainsWord(item.Category, "sport", StringComparison.OrdinalIgnoreCase) || GeneralHelpers.ContainsWord(item.Category, "motor sports", StringComparison.OrdinalIgnoreCase) || GeneralHelpers.ContainsWord(item.Category, "football", StringComparison.OrdinalIgnoreCase) || GeneralHelpers.ContainsWord(item.Category, "cricket", StringComparison.OrdinalIgnoreCase) }; if (Plugin.Instance.RecordingUncs.Count > 0) { foreach (string unc in Plugin.Instance.RecordingUncs) { string recPath = Path.Combine(unc, item.FileName); if (File.Exists(recPath)) { val.Path = recPath; break; } } } val.Genres.AddRange(item.Category.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)); if (item.Artwork.ArtworkInfos.Count() > 0) { val.HasImage = true; val.ImageUrl = string.Format("{0}{1}", Plugin.Instance.Configuration.WebServiceUrl, item.Artwork.ArtworkInfos[0].URL); } else { val.HasImage = false; } ret.Add(val); } } } return(ret); }
/// <summary> /// Ensure that we are connected to the NextPvr server /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> private async Task EnsureSetup() { var config = Plugin.Instance.Configuration; if (string.IsNullOrEmpty(config.Host)) { _logger.Error("[MythTV] Host must be configured."); throw new InvalidOperationException("MythTV host must be configured."); } List <StorageGroupDir> storageGroups; using (var stream = await _httpClient.Get(GetOptions(CancellationToken.None, "/Myth/GetStorageGroupDirs")).ConfigureAwait(false)) { storageGroups = new MythResponse().GetStorageGroupDirs(stream, _jsonSerializer, _logger, true); } List <StorageGroupMap> storageGroupMaps = config.StorageGroupMaps; if (!storageGroupMaps.Any()) { storageGroupMaps = storageGroups.Select(x => new StorageGroupMap { GroupName = x.GroupName, DirName = x.DirName, DirNameEmby = x.DirName }).ToList(); } else { // drop groups no longer on server storageGroupMaps.RemoveAll(g => !storageGroups.Select(x => x.GroupName).Contains(g.GroupName)); // add in new groups from server List <StorageGroupDir> newGroups = storageGroups; newGroups.RemoveAll(g => storageGroupMaps.Select(x => x.GroupName).Contains(g.GroupName)); storageGroupMaps.AddRange(newGroups.Select(x => new StorageGroupMap { GroupName = x.GroupName, DirName = x.DirName, DirNameEmby = x.DirName })); } // make sure there are no trailing path separators foreach (var group in storageGroupMaps) { group.DirName = group.DirName.TrimEnd('/'); group.DirNameEmby = group.DirNameEmby.TrimEnd('/'); } Plugin.Instance.Configuration.StorageGroupMaps = storageGroupMaps; List <string> recGroupNames; using (var stream = await _httpClient.Get(GetOptions(CancellationToken.None, "/Dvr/GetRecGroupList")).ConfigureAwait(false)) { recGroupNames = new DvrResponse().GetRecGroupList(stream, _jsonSerializer, _logger); } List <RecGroup> recGroups = config.RecGroups; if (!recGroups.Any()) { recGroups = recGroupNames.Select(x => new RecGroup(x)).ToList(); } else { // drop groups no longer on server recGroups.RemoveAll(g => !recGroupNames.Contains(g.Name)); // add in new groups from server recGroups.AddRange(recGroupNames.Except(recGroups.Select(x => x.Name)).Select(g => new RecGroup(g)).ToList()); } Plugin.Instance.Configuration.RecGroups = recGroups; Plugin.Instance.SaveConfiguration(); if (config.UseSchedulesDirectImages) { _imageGrabber = new SchedulesDirectImages(_httpClient, _jsonSerializer, _logger); } }