public Task <IEnumerable <SeriesTimerInfo> > buildAutorecInfos(CancellationToken cancellationToken) { return(Task.Factory.StartNew <IEnumerable <SeriesTimerInfo> >(() => { lock (_data) { List <SeriesTimerInfo> result = new List <SeriesTimerInfo>(); foreach (KeyValuePair <string, HTSMessage> entry in _data) { if (cancellationToken.IsCancellationRequested) { _logger.Info("[TVHclient] DvrDataHelper.buildDvrInfos, call canceled - returning part list."); return result; } HTSMessage m = entry.Value; SeriesTimerInfo sti = new SeriesTimerInfo(); try { if (m.containsField("id")) { sti.Id = m.getString("id"); } } catch (InvalidCastException) { } try { if (m.containsField("daysOfWeek")) { int daysOfWeek = m.getInt("daysOfWeek"); sti.Days = getDayOfWeekListFromInt(daysOfWeek); } } catch (InvalidCastException) { } sti.StartDate = DateTime.Now.ToUniversalTime(); try { if (m.containsField("retention")) { int retentionInDays = m.getInt("retention"); if (DateTime.MaxValue.AddDays(-retentionInDays) < DateTime.Now) { _logger.Error("[TVHclient] Change during 'EndDate' calculation: set retention value from '" + retentionInDays + "' to '365' days"); sti.EndDate = DateTime.Now.AddDays(365).ToUniversalTime(); } else { sti.EndDate = DateTime.Now.AddDays(retentionInDays).ToUniversalTime(); } } } catch (Exception e) { _logger.Error("[TVHclient] Exception during 'EndDate' calculation: " + e.Message + "\n" + e + "\n" + m.ToString()); } try { if (m.containsField("channel")) { sti.ChannelId = "" + m.getInt("channel"); } } catch (InvalidCastException) { } try { if (m.containsField("startExtra")) { sti.PrePaddingSeconds = (int)m.getLong("startExtra") * 60; sti.IsPrePaddingRequired = true; } } catch (InvalidCastException) { } try { if (m.containsField("stopExtra")) { sti.PostPaddingSeconds = (int)m.getLong("stopExtra") * 60; sti.IsPostPaddingRequired = true; } } catch (InvalidCastException) { } try { if (m.containsField("title")) { sti.Name = m.getString("title"); } } catch (InvalidCastException) { } try { if (m.containsField("description")) { sti.Overview = m.getString("description"); } } catch (InvalidCastException) { } try { if (m.containsField("priority")) { sti.Priority = m.getInt("priority"); } } catch (InvalidCastException) { } try { if (m.containsField("title")) { sti.SeriesId = m.getString("title"); } } catch (InvalidCastException) { } /* * public string ProgramId { get; set; } * public bool RecordAnyChannel { get; set; } * public bool RecordAnyTime { get; set; } * public bool RecordNewOnly { get; set; } */ result.Add(sti); } return result; } })); }
public Task <IEnumerable <TimerInfo> > buildPendingTimersInfos(CancellationToken cancellationToken) { return(Task.Factory.StartNew <IEnumerable <TimerInfo> >(() => { lock (_data) { List <TimerInfo> result = new List <TimerInfo>(); foreach (KeyValuePair <string, HTSMessage> entry in _data) { if (cancellationToken.IsCancellationRequested) { _logger.Info("[TVHclient] DvrDataHelper.buildDvrInfos, call canceled - returning part list."); return result; } HTSMessage m = entry.Value; TimerInfo ti = new TimerInfo(); try { if (m.containsField("id")) { ti.Id = "" + m.getInt("id"); } } catch (InvalidCastException) { } try { if (m.containsField("channel")) { ti.ChannelId = "" + m.getInt("channel"); } } catch (InvalidCastException) { } try { if (m.containsField("start")) { long unixUtc = m.getLong("start"); ti.StartDate = _initialDateTimeUTC.AddSeconds(unixUtc).ToUniversalTime(); } } catch (InvalidCastException) { } try { if (m.containsField("stop")) { long unixUtc = m.getLong("stop"); ti.EndDate = _initialDateTimeUTC.AddSeconds(unixUtc).ToUniversalTime(); } } catch (InvalidCastException) { } try { if (m.containsField("title")) { ti.Name = m.getString("title"); } } catch (InvalidCastException) { } try { if (m.containsField("description")) { ti.Overview = m.getString("description"); } } catch (InvalidCastException) { } try { if (m.containsField("state")) { string state = m.getString("state"); switch (state) { case "scheduled": ti.Status = RecordingStatus.Scheduled; break; default: // only scheduled timers need to be delivered continue; } } } catch (InvalidCastException) { } try { if (m.containsField("startExtra")) { ti.PrePaddingSeconds = (int)m.getLong("startExtra") * 60; ti.IsPrePaddingRequired = true; } } catch (InvalidCastException) { } try { if (m.containsField("stopExtra")) { ti.PostPaddingSeconds = (int)m.getLong("stopExtra") * 60; ti.IsPostPaddingRequired = true; } } catch (InvalidCastException) { } try { if (m.containsField("priority")) { ti.Priority = m.getInt("priority"); } } catch (InvalidCastException) { } try { if (m.containsField("autorecId")) { ti.SeriesTimerId = m.getString("autorecId"); } } catch (InvalidCastException) { } try { if (m.containsField("eventId")) { ti.ProgramId = "" + m.getInt("eventId"); } } catch (InvalidCastException) { } result.Add(ti); } return result; } })); }
public void onMessage(HTSMessage response) { if (response != null) { switch (response.Method) { case "tagAdd": case "tagUpdate": case "tagDelete": //_logger.Fatal("[TVHclient] tad add/update/delete" + response.ToString()); break; case "channelAdd": case "channelUpdate": _channelDataHelper.Add(response); break; case "dvrEntryAdd": _dvrDataHelper.dvrEntryAdd(response); break; case "dvrEntryUpdate": _dvrDataHelper.dvrEntryUpdate(response); break; case "dvrEntryDelete": _dvrDataHelper.dvrEntryDelete(response); break; case "autorecEntryAdd": _autorecDataHelper.autorecEntryAdd(response); break; case "autorecEntryUpdate": _autorecDataHelper.autorecEntryUpdate(response); break; case "autorecEntryDelete": _autorecDataHelper.autorecEntryDelete(response); break; case "eventAdd": case "eventUpdate": case "eventDelete": // should not happen as we don't subscribe for this events. break; //case "subscriptionStart": //case "subscriptionGrace": //case "subscriptionStop": //case "subscriptionSkip": //case "subscriptionSpeed": //case "subscriptionStatus": // _logger.Fatal("[TVHclient] subscription events " + response.ToString()); // break; //case "queueStatus": // _logger.Fatal("[TVHclient] queueStatus event " + response.ToString()); // break; //case "signalStatus": // _logger.Fatal("[TVHclient] signalStatus event " + response.ToString()); // break; //case "timeshiftStatus": // _logger.Fatal("[TVHclient] timeshiftStatus event " + response.ToString()); // break; //case "muxpkt": // streaming data // _logger.Fatal("[TVHclient] muxpkt event " + response.ToString()); // break; case "initialSyncCompleted": _initialLoadFinished = true; break; default: //_logger.Fatal("[TVHclient] Method '" + response.Method + "' not handled in LiveTvService.cs"); break; } } }
public async Task <MediaSourceInfo> GetRecordingStream(string recordingId, string mediaSourceId, CancellationToken cancellationToken) { HTSMessage getTicketMessage = new HTSMessage(); getTicketMessage.Method = "getTicket"; getTicketMessage.putField("dvrId", recordingId); TaskWithTimeoutRunner <HTSMessage> twtr = new TaskWithTimeoutRunner <HTSMessage>(TIMEOUT); TaskWithTimeoutResult <HTSMessage> twtRes = await twtr.RunWithTimeout(Task.Factory.StartNew <HTSMessage>(() => { LoopBackResponseHandler lbrh = new LoopBackResponseHandler(); _htsConnectionHandler.SendMessage(getTicketMessage, lbrh); return(lbrh.getResponse()); })); if (twtRes.HasTimeout) { _logger.LogError("[TVHclient] Timeout obtaining playback authentication ticket from TVH"); } else { HTSMessage getTicketResponse = twtRes.Result; if (_subscriptionId == int.MaxValue) { _subscriptionId = 0; } int currSubscriptionId = _subscriptionId++; if (_htsConnectionHandler.GetEnableSubsMaudios()) { _logger.LogInformation("[TVHclient] Support for live TV subtitles and multiple audio tracks is enabled."); MediaSourceInfo recordingasset = new MediaSourceInfo(); recordingasset.Id = "" + currSubscriptionId; // Use HTTP basic auth instead of TVH ticketing system for authentication to allow the users to switch subs or audio tracks at any time recordingasset.Path = _htsConnectionHandler.GetHttpBaseUrl() + getTicketResponse.getString("path"); recordingasset.Protocol = MediaProtocol.Http; // Set asset source and type for stream probing and logging string recordingasset_probeUrl = "" + recordingasset.Path; // If enabled, force video deinterlacing for recordings if (_htsConnectionHandler.GetForceDeinterlace()) { _logger.LogInformation("[TVHclient] Force video deinterlacing for all channels and recordings is enabled."); foreach (MediaStream i in recordingasset.MediaStreams) { if (i.Type == MediaStreamType.Video && i.IsInterlaced == false) { i.IsInterlaced = true; } } } return(recordingasset); } else { return(new MediaSourceInfo { Id = "" + currSubscriptionId, Path = _htsConnectionHandler.GetHttpBaseUrl() + getTicketResponse.getString("path") + "?ticket=" + getTicketResponse.getString("ticket"), Protocol = MediaProtocol.Http, 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, // Set to true if unknown to enable deinterlacing IsInterlaced = true }, 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 } } }); } } throw new TimeoutException(); }
public Task <IEnumerable <ChannelInfo> > BuildChannelInfos(CancellationToken cancellationToken) { return(Task.Factory.StartNew <IEnumerable <ChannelInfo> >(() => { lock (_data) { List <ChannelInfo> result = new List <ChannelInfo>(); foreach (KeyValuePair <int, HTSMessage> entry in _data) { if (cancellationToken.IsCancellationRequested) { _logger.LogInformation("[TVHclient] ChannelDataHelper.buildChannelInfos, call canceled - returning part list."); return result; } HTSMessage m = entry.Value; try { ChannelInfo ci = new ChannelInfo(); ci.Id = "" + entry.Key; ci.ImagePath = ""; if (m.containsField("channelIcon")) { string channelIcon = m.getString("channelIcon"); Uri uriResult; bool uriCheckResult = Uri.TryCreate(channelIcon, UriKind.Absolute, out uriResult) && uriResult.Scheme == Uri.UriSchemeHttp; if (uriCheckResult) { ci.ImageUrl = channelIcon; } else { ci.HasImage = true; if (!_piconData.ContainsKey(ci.Id)) { _piconData.Add(ci.Id, channelIcon); } } } if (m.containsField("channelName")) { string name = m.getString("channelName"); if (string.IsNullOrEmpty(name)) { continue; } ci.Name = m.getString("channelName"); } if (m.containsField("channelNumber")) { int channelNumber = m.getInt("channelNumber"); ci.Number = "" + channelNumber; if (m.containsField("channelNumberMinor")) { int channelNumberMinor = m.getInt("channelNumberMinor"); ci.Number = ci.Number + "." + channelNumberMinor; } } Boolean serviceFound = false; if (m.containsField("services")) { IList tunerInfoList = m.getList("services"); if (tunerInfoList != null && tunerInfoList.Count > 0) { HTSMessage firstServiceInList = (HTSMessage)tunerInfoList[0]; if (firstServiceInList.containsField("type")) { string type = firstServiceInList.getString("type").ToLower(); switch (type) { case "radio": ci.ChannelType = ChannelType.Radio; serviceFound = true; break; case "sdtv": case "hdtv": case "uhdtv": ci.ChannelType = ChannelType.TV; serviceFound = true; break; case "other": switch (_channelType4Other.ToLower()) { case "tv": _logger.LogInformation("[TVHclient] ChannelDataHelper: map service tag 'Other' to 'TV'."); ci.ChannelType = ChannelType.TV; serviceFound = true; break; case "radio": _logger.LogInformation("[TVHclient] ChannelDataHelper: map service tag 'Other' to 'Radio'."); ci.ChannelType = ChannelType.Radio; serviceFound = true; break; default: _logger.LogInformation("[TVHclient] ChannelDataHelper: don't map service tag 'Other' - will be ignored."); break; } break; default: _logger.LogInformation("[TVHclient] ChannelDataHelper: unkown service tag '{tag}' - will be ignored.", type); break; } } } } if (!serviceFound) { _logger.LogInformation("[TVHclient] ChannelDataHelper: unable to detect service-type (tvheadend tag!!!) from service list: {m}", m.ToString()); continue; } _logger.LogInformation("[TVHclient] ChannelDataHelper: Adding channel: {m}", m.ToString()); result.Add(ci); } catch (Exception ex) { _logger.LogError(ex, "[TVHclient] ChannelDataHelper.BuildChannelInfos caught exception. HTSmessage: {m}", m); } } return result; } })); }
public void SendMessage(HTSMessage message, HTSResponseHandler responseHandler) { ensureConnection(); _htsConnection.sendMessage(message, responseHandler); }
public List <ChannelInfo> BuildChannelInfos(string baseHttpUrlWithAuth) { var result = new List <ChannelInfo>(); var allChannels = _data.ToArray(); foreach (KeyValuePair <int, HTSMessage> entry in allChannels) { HTSMessage m = entry.Value; try { var ci = new ChannelInfo(); ci.Id = entry.Key.ToString(CultureInfo.InvariantCulture); if (m.containsField("channelIcon")) { string channelIcon = m.getString("channelIcon"); Uri uriResult; bool uriCheckResult = Uri.TryCreate(channelIcon, UriKind.Absolute, out uriResult) && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); if (uriCheckResult) { ci.ImageUrl = channelIcon; } else { ci.ImageUrl = baseHttpUrlWithAuth.TrimEnd('/') + "/" + channelIcon; } } if (m.containsField("channelName")) { string name = m.getString("channelName"); if (string.IsNullOrEmpty(name)) { continue; } ci.Name = m.getString("channelName"); } if (m.containsField("channelNumber")) { int channelNumber = m.getInt("channelNumber"); ci.Number = "" + channelNumber; if (m.containsField("channelNumberMinor")) { int channelNumberMinor = m.getInt("channelNumberMinor"); ci.Number = ci.Number + "." + channelNumberMinor; } } Boolean serviceFound = false; if (m.containsField("services")) { IList tunerInfoList = m.getList("services"); if (tunerInfoList != null && tunerInfoList.Count > 0) { HTSMessage firstServiceInList = (HTSMessage)tunerInfoList[0]; if (firstServiceInList.containsField("type")) { string type = firstServiceInList.getString("type").ToLower(); switch (type) { case "radio": ci.ChannelType = ChannelType.Radio; serviceFound = true; break; case "sdtv": case "hdtv": case "uhdtv": case "fhdtv": ci.ChannelType = ChannelType.TV; serviceFound = true; break; default: _logger.Info("[TVHclient] ChannelDataHelper: unkown service tag '" + type + "' - will be ignored."); break; } } } } if (!serviceFound) { _logger.Info("[TVHclient] ChannelDataHelper: unable to detect service-type (tvheadend tag!!!) from service list:" + m.ToString()); continue; } _logger.Info("[TVHclient] ChannelDataHelper: Adding channel \n" + m.ToString()); result.Add(ci); } catch (Exception ex) { _logger.Error("[TVHclient] ChannelDataHelper.BuildChannelInfos caught exception: " + ex.Message + "\nHTSmessage=" + m); } } return(result); }
public Task <IEnumerable <ChannelInfo> > buildChannelInfos(CancellationToken cancellationToken) { return(Task.Factory.StartNew <IEnumerable <ChannelInfo> >(() => { lock (_data) { List <ChannelInfo> result = new List <ChannelInfo>(); foreach (KeyValuePair <int, HTSMessage> entry in _data) { if (cancellationToken.IsCancellationRequested) { _logger.Info("[TVHclient] ChannelDataHelper.buildChannelInfos, call canceled - returning part list."); return result; } HTSMessage m = entry.Value; ChannelInfo ci = new ChannelInfo(); ci.Id = "" + entry.Key; ci.ImagePath = ""; if (m.containsField("channelIcon")) { string channelIcon = m.getString("channelIcon"); Uri uriResult; bool uriCheckResult = Uri.TryCreate(channelIcon, UriKind.Absolute, out uriResult) && uriResult.Scheme == Uri.UriSchemeHttp; if (uriCheckResult) { ci.ImageUrl = channelIcon; } else { _logger.Info("[TVHclient] ChannelDataHelper.buildChannelInfos: channelIcon '" + channelIcon + "' is not a valid HTTP URL!"); } } if (m.containsField("channelName")) { string name = m.getString("channelName"); if (string.IsNullOrEmpty(name)) { continue; } ci.Name = m.getString("channelName"); } if (m.containsField("channelNumber")) { int chNo = m.getInt("channelNumber"); ci.Number = "" + chNo; } if (m.containsField("services")) { IList tunerInfoList = m.getList("services"); HTSMessage firstServiceInList = (HTSMessage)tunerInfoList[0]; if (firstServiceInList.containsField("type")) { string type = firstServiceInList.getString("type"); switch (type) { case "Radio": ci.ChannelType = ChannelType.Radio; //continue; break; case "SDTV": case "HDTV": ci.ChannelType = ChannelType.TV; break; default: _logger.Error("[TVHclient] ChannelDataHelper: unkown service type '" + type + "'."); break; } } } else { _logger.Error("[TVHclient] ChannelDataHelper: unable to detect service-type from service list:" + m.ToString()); continue; } result.Add(ci); } return result; } })); }
public Task <IEnumerable <ChannelInfo> > buildChannelInfos(CancellationToken cancellationToken) { return(Task.Factory.StartNew <IEnumerable <ChannelInfo> >(() => { lock (_data) { List <ChannelInfo> result = new List <ChannelInfo>(); foreach (KeyValuePair <int, HTSMessage> entry in _data) { if (cancellationToken.IsCancellationRequested) { _logger.Info("[TVHclient] ChannelDataHelper.buildChannelInfos, call canceled - returning part list."); return result; } HTSMessage m = entry.Value; ChannelInfo ci = new ChannelInfo(); ci.Id = "" + entry.Key; ci.ImagePath = ""; if (m.containsField("channelIcon")) { string channelIcon = m.getString("channelIcon"); Uri uriResult; bool uriCheckResult = Uri.TryCreate(channelIcon, UriKind.Absolute, out uriResult) && uriResult.Scheme == Uri.UriSchemeHttp; if (uriCheckResult) { ci.ImageUrl = channelIcon; } else if (channelIcon.ToLower().StartsWith("picon://")) { ci.HasImage = true; _piconData.Add(ci.Id, channelIcon); } else { _logger.Info("[TVHclient] ChannelDataHelper.buildChannelInfos: channelIcon '" + channelIcon + "' can not be handled properly for channelID '" + ci.Id + "'!"); } } if (m.containsField("channelName")) { string name = m.getString("channelName"); if (string.IsNullOrEmpty(name)) { continue; } ci.Name = m.getString("channelName"); } if (m.containsField("channelNumber")) { int chNo = m.getInt("channelNumber"); ci.Number = "" + chNo; } Boolean serviceFound = false; if (m.containsField("services")) { IList tunerInfoList = m.getList("services"); if (tunerInfoList != null && tunerInfoList.Count > 0) { HTSMessage firstServiceInList = (HTSMessage)tunerInfoList[0]; if (firstServiceInList.containsField("type")) { string type = firstServiceInList.getString("type").ToLower(); switch (type) { case "radio": ci.ChannelType = ChannelType.Radio; serviceFound = true; break; case "sdtv": case "hdtv": ci.ChannelType = ChannelType.TV; serviceFound = true; break; case "other": switch (_channelType4Other.ToLower()) { case "tv": _logger.Info("[TVHclient] ChannelDataHelper: map service type 'Other' to 'TV'."); ci.ChannelType = ChannelType.TV; serviceFound = true; break; case "radio": _logger.Info("[TVHclient] ChannelDataHelper: map service type 'Other' to 'Radio'."); ci.ChannelType = ChannelType.Radio; serviceFound = true; break; default: _logger.Error("[TVHclient] ChannelDataHelper: don't map service type 'Other' - will be ignored."); break; } break; default: _logger.Error("[TVHclient] ChannelDataHelper: unkown service type '" + type + "' - will be ignored."); break; } } } } if (!serviceFound) { _logger.Error("[TVHclient] ChannelDataHelper: unable to detect service-type from service list:" + m.ToString()); continue; } result.Add(ci); } return result; } })); }
public Task <IEnumerable <MyRecordingInfo> > buildDvrInfos(CancellationToken cancellationToken) { return(Task.Factory.StartNew <IEnumerable <MyRecordingInfo> >(() => { lock (_data) { List <MyRecordingInfo> result = new List <MyRecordingInfo>(); foreach (KeyValuePair <string, HTSMessage> entry in _data) { if (cancellationToken.IsCancellationRequested) { _logger.LogDebug("[TVHclient] DvrDataHelper.buildDvrInfos: call cancelled - returning partial list"); return result; } HTSMessage m = entry.Value; MyRecordingInfo ri = new MyRecordingInfo(); try { if (m.containsField("error")) { // When TVHeadend recordings are removed, their info can // still be kept around with a status of "completed". // The only way to identify them is from the error string // which is set to "File missing". Use that to not show // non-existing deleted recordings. if (m.getString("error").Contains("missing")) { continue; } } } catch (InvalidCastException) { } try { if (m.containsField("id")) { ri.Id = "" + m.getInt("id"); } } catch (InvalidCastException) { } try { if (m.containsField("path")) { ri.Path = "" + m.getString("path"); } } catch (InvalidCastException) { } try { if (m.containsField("url")) { ri.Url = "" + m.getString("url"); } } catch (InvalidCastException) { } try { if (m.containsField("channel")) { ri.ChannelId = "" + m.getInt("channel"); } } catch (InvalidCastException) { } try { if (m.containsField("start")) { long unixUtc = m.getLong("start"); ri.StartDate = _initialDateTimeUTC.AddSeconds(unixUtc).ToUniversalTime(); } } catch (InvalidCastException) { } try { if (m.containsField("stop")) { long unixUtc = m.getLong("stop"); ri.EndDate = _initialDateTimeUTC.AddSeconds(unixUtc).ToUniversalTime(); } } catch (InvalidCastException) { } try { if (m.containsField("title")) { ri.Name = m.getString("title"); } } catch (InvalidCastException) { } try { if (m.containsField("description")) { ri.Overview = m.getString("description"); } } catch (InvalidCastException) { } try { if (m.containsField("summary")) { ri.EpisodeTitle = m.getString("summary"); } } catch (InvalidCastException) { } ri.HasImage = false; // public string ImagePath { get; set; } // public string ImageUrl { get; set; } try { if (m.containsField("state")) { string state = m.getString("state"); switch (state) { case "completed": ri.Status = RecordingStatus.Completed; break; case "scheduled": ri.Status = RecordingStatus.New; continue; //break; case "missed": ri.Status = RecordingStatus.Error; break; case "recording": ri.Status = RecordingStatus.InProgress; break; default: _logger.LogCritical("[TVHclient] DvrDataHelper.buildDvrInfos: state '{state}' not handled", state); continue; //break; } } } catch (InvalidCastException) { } // Path must not be set to force emby use of the LiveTvService methods!!!! //if (m.containsField("path")) //{ // ri.Path = m.getString("path"); //} try { if (m.containsField("autorecId")) { ri.SeriesTimerId = m.getString("autorecId"); } } catch (InvalidCastException) { } try { if (m.containsField("eventId")) { ri.ProgramId = "" + m.getInt("eventId"); } } catch (InvalidCastException) { } /* * public ProgramAudio? Audio { get; set; } * public ChannelType ChannelType { get; set; } * public float? CommunityRating { get; set; } * public List<string> Genres { get; set; } * public bool? IsHD { get; set; } * public bool IsKids { get; set; } * public bool IsLive { get; set; } * public bool IsMovie { get; set; } * public bool IsNews { get; set; } * public bool IsPremiere { get; set; } * public bool IsRepeat { get; set; } * public bool IsSeries { get; set; } * public bool IsSports { get; set; } * public string OfficialRating { get; set; } * public DateTime? OriginalAirDate { get; set; } * public string Url { get; set; } */ result.Add(ri); } return result; } })); }
public async Task <MediaSourceInfo> GetRecordingStream(string recordingId, string mediaSourceId, CancellationToken cancellationToken) { ensureConnection(); HTSMessage getTicketMessage = new HTSMessage(); getTicketMessage.Method = "getTicket"; getTicketMessage.putField("dvrId", recordingId); //HTSMessage getTicketResponse = await Task.Factory.StartNew<HTSMessage>(() => //{ // LoopBackResponseHandler lbrh = new LoopBackResponseHandler(); // _htsConnection.sendMessage(getTicketMessage, lbrh); // return lbrh.getResponse(); //}); TaskWithTimeoutRunner <HTSMessage> twtr = new TaskWithTimeoutRunner <HTSMessage>(TIMEOUT); TaskWithTimeoutResult <HTSMessage> twtRes = await twtr.RunWithTimeout(Task.Factory.StartNew <HTSMessage>(() => { LoopBackResponseHandler lbrh = new LoopBackResponseHandler(); _htsConnection.sendMessage(getTicketMessage, lbrh); return(lbrh.getResponse()); })); if (twtRes.HasTimeout) { _logger.Error("[TVHclient] Can't delete recording because of timeout"); } else { HTSMessage getTicketResponse = twtRes.Result; if (_subscriptionId == int.MaxValue) { _subscriptionId = 0; } int currSubscriptionId = _subscriptionId++; return(new MediaSourceInfo { Id = "" + currSubscriptionId, Path = _httpBaseUrl + getTicketResponse.getString("path") + "?ticket=" + getTicketResponse.getString("ticket"), Protocol = MediaProtocol.Http, 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, // Set to true if unknown to enable deinterlacing IsInterlaced = true }, 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 } } }); } throw new TimeoutException(); }
public async Task <T> SendMessage <T>(HTSMessage message, Func <HTSMessage, T> responseHandler, CancellationToken cancellationToken) { var response = await SendMessage(message, cancellationToken).ConfigureAwait(false); return(responseHandler(response)); }
public async Task <HTSMessage> SendMessage(HTSMessage message, CancellationToken cancellationToken) { await EnsureConnection(cancellationToken).ConfigureAwait(false); return(await _htsConnection.SendMessage(message, cancellationToken).ConfigureAwait(false)); }
public Task <IEnumerable <RecordingInfo> > buildDvrInfos(CancellationToken cancellationToken) { return(Task.Factory.StartNew <IEnumerable <RecordingInfo> >(() => { lock (_data) { List <RecordingInfo> result = new List <RecordingInfo>(); foreach (KeyValuePair <string, HTSMessage> entry in _data) { if (cancellationToken.IsCancellationRequested) { _logger.Info("[TVHclient] DvrDataHelper.buildDvrInfos, call canceled - returning part list."); return result; } HTSMessage m = entry.Value; RecordingInfo ri = new RecordingInfo(); try { if (m.containsField("id")) { ri.Id = "" + m.getInt("id"); } } catch (InvalidCastException) { } try { if (m.containsField("channel")) { ri.ChannelId = "" + m.getInt("channel"); } } catch (InvalidCastException) { } try { if (m.containsField("start")) { long unixUtc = m.getLong("start"); ri.StartDate = _initialDateTimeUTC.AddSeconds(unixUtc).ToUniversalTime(); } } catch (InvalidCastException) { } try { if (m.containsField("stop")) { long unixUtc = m.getLong("stop"); ri.EndDate = _initialDateTimeUTC.AddSeconds(unixUtc).ToUniversalTime(); } } catch (InvalidCastException) { } try { if (m.containsField("title")) { ri.Name = m.getString("title"); } } catch (InvalidCastException) { } try { if (m.containsField("description")) { ri.Overview = m.getString("description"); } } catch (InvalidCastException) { } try { if (m.containsField("summary")) { ri.EpisodeTitle = m.getString("summary"); } } catch (InvalidCastException) { } ri.HasImage = false; // public string ImagePath { get; set; } // public string ImageUrl { get; set; } try { if (m.containsField("state")) { string state = m.getString("state"); switch (state) { case "completed": ri.Status = RecordingStatus.Completed; break; case "scheduled": ri.Status = RecordingStatus.Scheduled; continue; //break; case "missed": ri.Status = RecordingStatus.Error; break; case "recording": ri.Status = RecordingStatus.InProgress; break; default: _logger.Fatal("[TVHclient] DvrDataHelper.buildDvrInfos: state '" + state + "' not handled!"); continue; //break; } } } catch (InvalidCastException) { } // Path must not be set to force emby use of the LiveTvService methods!!!! //if (m.containsField("path")) //{ // ri.Path = m.getString("path"); //} try { if (m.containsField("autorecId")) { ri.SeriesTimerId = m.getString("autorecId"); } } catch (InvalidCastException) { } try { if (m.containsField("eventId")) { ri.ProgramId = "" + m.getInt("eventId"); } } catch (InvalidCastException) { } /* * public ProgramAudio? Audio { get; set; } * public ChannelType ChannelType { get; set; } * public float? CommunityRating { get; set; } * public List<string> Genres { get; set; } * public bool? IsHD { get; set; } * public bool IsKids { get; set; } * public bool IsLive { get; set; } * public bool IsMovie { get; set; } * public bool IsNews { get; set; } * public bool IsPremiere { get; set; } * public bool IsRepeat { get; set; } * public bool IsSeries { get; set; } * public bool IsSports { get; set; } * public string OfficialRating { get; set; } * public DateTime? OriginalAirDate { get; set; } * public string Url { get; set; } */ result.Add(ri); } return result; } })); }
public void handleResponse(HTSMessage response) { _responseDataQueue.Enqueue(response); }
public void handleResponse(HTSMessage response) { _logger.LogInformation("[TVHclient] GetEventsResponseHandler.handleResponse: received answer from TVH server: {msg}", response.ToString()); if (response.containsField("events")) { IList events = response.getList("events"); foreach (HTSMessage currEventMessage in events) { ProgramInfo pi = new ProgramInfo(); if (currEventMessage.containsField("start")) { long currStartTimeUnix = currEventMessage.getLong("start"); DateTime currentStartDateTimeUTC = _initialDateTimeUTC.AddSeconds(currStartTimeUnix).ToUniversalTime(); int compResult = DateTime.Compare(currentStartDateTimeUTC, _endDateTimeUtc); if (compResult > 0) { _logger.LogInformation("[TVHclient] GetEventsResponseHandler.handleResponse: start value of event larger query stop value - skipping! \n" + "Query start UTC dateTime: {start}\n" + "Query end UTC dateTime: {end}\n" + "Event start UTC dateTime: {currstart}\n{msg}", _startDateTimeUtc, _endDateTimeUtc, currentStartDateTimeUTC, currEventMessage.ToString()); continue; } pi.StartDate = currentStartDateTimeUTC; } else { _logger.LogInformation("[TVHclient] GetEventsResponseHandler.handleResponse: no start value for event - skipping!\n{msg}", currEventMessage.ToString()); continue; } if (currEventMessage.containsField("stop")) { long currEndTimeUnix = currEventMessage.getLong("stop"); DateTime currentEndDateTimeUTC = _initialDateTimeUTC.AddSeconds(currEndTimeUnix).ToUniversalTime(); int compResult = DateTime.Compare(currentEndDateTimeUTC, _startDateTimeUtc); if (compResult < 0) { _logger.LogInformation("[TVHclient] GetEventsResponseHandler.handleResponse: stop value of event smaller query start value - skipping!\n" + "Query start UTC dateTime: {start}\n" + "Query end UTC dateTime: {end}\n" + "Event start UTC dateTime: {currend}\n{msg}", _startDateTimeUtc, _endDateTimeUtc, currentEndDateTimeUTC, currEventMessage.ToString()); continue; } pi.EndDate = currentEndDateTimeUTC; } else { _logger.LogInformation("[TVHclient] GetEventsResponseHandler.handleResponse: no stop value for event - skipping!\n{msg}", currEventMessage.ToString()); continue; } if (currEventMessage.containsField("channelId")) { pi.ChannelId = "" + currEventMessage.getInt("channelId"); } if (currEventMessage.containsField("eventId")) { pi.Id = "" + currEventMessage.getInt("eventId"); } if (currEventMessage.containsField("serieslinkId")) { pi.SeriesId = "" + currEventMessage.getInt("serieslinkId"); } if (currEventMessage.containsField("episodeNumber")) { pi.EpisodeNumber = currEventMessage.getInt("episodeNumber"); } else if (currEventMessage.containsField("episodeId")) { pi.EpisodeNumber = currEventMessage.getInt("episodeId"); } if (currEventMessage.containsField("seasonNumber")) { pi.SeasonNumber = currEventMessage.getInt("seasonNumber"); } else if (currEventMessage.containsField("seasonId")) { pi.SeasonNumber = currEventMessage.getInt("seasonId"); } if (currEventMessage.containsField("title")) { pi.Name = currEventMessage.getString("title"); } if (currEventMessage.containsField("description")) { pi.Overview = currEventMessage.getString("description"); } if (currEventMessage.containsField("summary")) { pi.EpisodeTitle = currEventMessage.getString("summary"); } if (currEventMessage.containsField("firstAired")) { long firstAiredUtcLong = currEventMessage.getLong("firstAired"); pi.OriginalAirDate = _initialDateTimeUTC.AddSeconds(firstAiredUtcLong).ToUniversalTime(); } if (currEventMessage.containsField("starRating")) { pi.OfficialRating = "" + currEventMessage.getInt("starRating"); } if (currEventMessage.containsField("image")) { pi.HasImage = true; pi.ImageUrl = "" + currEventMessage.getString("image"); } else { pi.HasImage = false; } if (currEventMessage.containsField("contentType")) { List <string> genres = new List <string>(); int contentType = currEventMessage.getInt("contentType"); //byte major = (byte)((contentTypeRaw & 0xF0) >> 4); //byte minor = (byte) (contentTypeRaw & 0xF); switch (contentType) { // movie/drama case 0x10: genres.Add("Drama"); genres.Add("Movie"); pi.IsMovie = true; break; case 0x11: genres.Add("Drama"); genres.Add("Movie"); genres.Add("Detective"); genres.Add("Thriller"); pi.IsMovie = true; break; case 0x12: genres.Add("Drama"); genres.Add("Movie"); genres.Add("Adventure"); genres.Add("Western"); genres.Add("War"); pi.IsMovie = true; break; case 0x13: genres.Add("Drama"); genres.Add("Movie"); genres.Add("Science Fiction"); genres.Add("Fantasy"); genres.Add("Horror"); pi.IsMovie = true; break; case 0x14: genres.Add("Drama"); genres.Add("Movie"); genres.Add("Comedy"); pi.IsMovie = true; break; case 0x15: genres.Add("Drama"); genres.Add("Movie"); genres.Add("Soap"); genres.Add("Melodrama"); genres.Add("Folkloric"); pi.IsMovie = true; break; case 0x16: genres.Add("Drama"); genres.Add("Movie"); genres.Add("Romance"); pi.IsMovie = true; break; case 0x17: genres.Add("Drama"); genres.Add("Movie"); genres.Add("Serious"); genres.Add("ClassicalReligion"); genres.Add("Historical"); pi.IsMovie = true; break; case 0x18: genres.Add("Drama"); genres.Add("Movie"); genres.Add("Adult Movie"); pi.IsMovie = true; break; // news/current affairs case 0x20: genres.Add("News"); genres.Add("Current Affairs"); pi.IsNews = true; break; case 0x21: genres.Add("News"); genres.Add("Current Affairs"); genres.Add("Weather Report"); pi.IsNews = true; break; case 0x22: genres.Add("News"); genres.Add("Current Affairs"); genres.Add("Magazine"); pi.IsNews = true; break; case 0x23: genres.Add("News"); genres.Add("Current Affairs"); genres.Add("Documentary"); pi.IsNews = true; break; case 0x24: genres.Add("News"); genres.Add("Current Affairs"); genres.Add("Discussion"); genres.Add("Interview"); genres.Add("Debate"); pi.IsNews = true; break; // show/game show case 0x30: genres.Add("Show"); genres.Add("Game Show"); break; case 0x31: genres.Add("Show"); genres.Add("Game Show"); genres.Add("Quiz"); genres.Add("Contest"); break; case 0x32: genres.Add("Show"); genres.Add("Game Show"); genres.Add("Variety"); break; case 0x33: genres.Add("Show"); genres.Add("Game Show"); genres.Add("Talk"); break; // sports case 0x40: genres.Add("Sports"); pi.IsSports = true; break; case 0x41: genres.Add("Sports"); genres.Add("Special Event"); pi.IsSports = true; break; case 0x42: genres.Add("Sports"); genres.Add("Magazine"); pi.IsSports = true; break; case 0x43: genres.Add("Sports"); genres.Add("Football"); genres.Add("Soccer"); pi.IsSports = true; break; case 0x44: genres.Add("Sports"); genres.Add("Tennis"); genres.Add("Squash"); pi.IsSports = true; break; case 0x45: genres.Add("Sports"); genres.Add("Team Sports"); pi.IsSports = true; break; case 0x46: genres.Add("Sports"); genres.Add("Athletics"); pi.IsSports = true; break; case 0x47: genres.Add("Sports"); genres.Add("Motor Sport"); pi.IsSports = true; break; case 0x48: genres.Add("Sports"); genres.Add("Water Sport"); pi.IsSports = true; break; case 0x49: genres.Add("Sports"); genres.Add("Winter Sport"); pi.IsSports = true; break; case 0x4a: genres.Add("Sports"); genres.Add("Equestrian"); pi.IsSports = true; break; case 0x4b: genres.Add("Sports"); genres.Add("Martial Sports"); pi.IsSports = true; break; // childrens/youth case 0x50: genres.Add("Childrens"); genres.Add("Youth"); pi.IsKids = true; break; case 0x51: genres.Add("Childrens"); genres.Add("Youth"); genres.Add("Pre-school"); pi.IsKids = true; break; case 0x52: genres.Add("Childrens"); genres.Add("Youth"); genres.Add("Entertainment (6 to 14 year-olds)"); pi.IsKids = true; break; case 0x53: genres.Add("Childrens"); genres.Add("Youth"); genres.Add("Entertainment (10 to 16 year-olds)"); pi.IsKids = true; break; case 0x54: genres.Add("Childrens"); genres.Add("Youth"); genres.Add("Informational"); genres.Add("Educational"); genres.Add("Schools"); pi.IsKids = true; break; case 0x55: genres.Add("Childrens"); genres.Add("Youth"); genres.Add("Cartoons"); genres.Add("Puppets"); pi.IsKids = true; break; // music/ballet/dance case 0x60: genres.Add("Music"); genres.Add("Ballet"); genres.Add("Dance"); break; case 0x61: genres.Add("Music"); genres.Add("Ballet"); genres.Add("Dance"); genres.Add("Pop"); genres.Add("Rock"); break; case 0x62: genres.Add("Music"); genres.Add("Ballet"); genres.Add("Dance"); genres.Add("Serious Music"); genres.Add("Classical Music"); break; case 0x63: genres.Add("Music"); genres.Add("Ballet"); genres.Add("Dance"); genres.Add("Folk"); genres.Add("Traditional Music"); break; case 0x64: genres.Add("Music"); genres.Add("Ballet"); genres.Add("Dance"); genres.Add("Jazz"); break; case 0x65: genres.Add("Music"); genres.Add("Ballet"); genres.Add("Dance"); genres.Add("Musical"); genres.Add("Opera"); break; case 0x66: genres.Add("Music"); genres.Add("Ballet"); genres.Add("Dance"); break; // arts/culture case 0x70: genres.Add("Arts"); genres.Add("Culture"); break; case 0x71: genres.Add("Arts"); genres.Add("Culture"); genres.Add("Performing Arts"); break; case 0x72: genres.Add("Arts"); genres.Add("Culture"); genres.Add("Fine Arts"); break; case 0x73: genres.Add("Arts"); genres.Add("Culture"); genres.Add("Religion"); break; case 0x74: genres.Add("Arts"); genres.Add("Culture"); genres.Add("Popular Culture"); genres.Add("Tradital Arts"); break; case 0x75: genres.Add("Arts"); genres.Add("Culture"); genres.Add("Literature"); break; case 0x76: genres.Add("Arts"); genres.Add("Culture"); genres.Add("Film"); genres.Add("Cinema"); break; case 0x77: genres.Add("Arts"); genres.Add("Culture"); genres.Add("Experimantal Film"); genres.Add("Video"); break; case 0x78: genres.Add("Arts"); genres.Add("Culture"); genres.Add("Broadcasting"); genres.Add("Press"); break; case 0x79: genres.Add("Arts"); genres.Add("Culture"); genres.Add("New Media"); break; case 0x7a: genres.Add("Arts"); genres.Add("Culture"); genres.Add("Magazine"); break; case 0x7b: genres.Add("Arts"); genres.Add("Culture"); genres.Add("Fashion"); break; // social/political/economic case 0x80: genres.Add("Social"); genres.Add("Political"); genres.Add("Economic"); break; case 0x81: genres.Add("Social"); genres.Add("Political"); genres.Add("Economic"); genres.Add("Magazin"); genres.Add("Report"); genres.Add("Documentary"); break; case 0x82: genres.Add("Social"); genres.Add("Political"); genres.Add("Economic"); genres.Add("Economics"); genres.Add("Social Advisory"); break; case 0x83: genres.Add("Social"); genres.Add("Political"); genres.Add("Economic"); genres.Add("Remarkable People"); break; // children's youth: educational/science/factual case 0x90: genres.Add("Educational"); genres.Add("Science"); genres.Add("Factual"); pi.IsKids = true; break; case 0x91: genres.Add("Educational"); genres.Add("Science"); genres.Add("Factual"); genres.Add("Nature"); genres.Add("Animals"); genres.Add("Environment"); pi.IsKids = true; break; case 0x92: genres.Add("Educational"); genres.Add("Science"); genres.Add("Factual"); genres.Add("Technology"); genres.Add("Natural Sciences"); pi.IsKids = true; break; case 0x93: genres.Add("Educational"); genres.Add("Science"); genres.Add("Factual"); genres.Add("Medicine"); genres.Add("Physiology"); genres.Add("Psychology"); pi.IsKids = true; break; case 0x94: genres.Add("Educational"); genres.Add("Science"); genres.Add("Factual"); genres.Add("Foreign Countries"); genres.Add("Expeditions"); pi.IsKids = true; break; case 0x95: genres.Add("Educational"); genres.Add("Science"); genres.Add("Factual"); genres.Add("Social"); genres.Add("Spiritual Sciences"); pi.IsKids = true; break; case 0x96: genres.Add("Educational"); genres.Add("Science"); genres.Add("Factual"); genres.Add("Further Education"); pi.IsKids = true; break; case 0x97: genres.Add("Educational"); genres.Add("Science"); genres.Add("Factual"); genres.Add("Languages"); pi.IsKids = true; break; // leisure hobbies case 0xa0: genres.Add("Leisure"); genres.Add("Hobbies"); break; case 0xa1: genres.Add("Leisure"); genres.Add("Hobbies"); genres.Add("Tourism"); genres.Add("Travel"); break; case 0xa2: genres.Add("Leisure"); genres.Add("Hobbies"); genres.Add("Handicraft"); break; case 0xa3: genres.Add("Leisure"); genres.Add("Hobbies"); genres.Add("Motoring"); break; case 0xa4: genres.Add("Leisure"); genres.Add("Hobbies"); genres.Add("Fitness"); genres.Add("Health"); break; case 0xa5: genres.Add("Leisure"); genres.Add("Hobbies"); genres.Add("Cooking"); break; case 0xa6: genres.Add("Leisure"); genres.Add("Hobbies"); genres.Add("Advertisement"); genres.Add("Shopping"); break; case 0xa7: genres.Add("Leisure"); genres.Add("Hobbies"); genres.Add("Gardening"); break; // misc case 0xb0: genres.Add("Original Language"); break; case 0xb1: genres.Add("Black and White"); break; case 0xb2: genres.Add("Unpublished"); break; case 0xb3: genres.Add("Live Broadcast"); pi.IsLive = true; break; // drama (user defined, specced in the UK "D-Book") case 0xf0: genres.Add("Drama"); pi.IsMovie = true; break; case 0xf1: genres.Add("Drama"); genres.Add("Detective"); genres.Add("Thriller"); pi.IsMovie = true; break; case 0xf2: genres.Add("Drama"); genres.Add("Adventure"); genres.Add("Western"); genres.Add("War"); pi.IsMovie = true; break; case 0xf3: genres.Add("Drama"); genres.Add("Science Fiction"); genres.Add("Fantasy"); genres.Add("Horror"); pi.IsMovie = true; break; case 0xf4: genres.Add("Drama"); genres.Add("Commedy"); pi.IsMovie = true; break; case 0xf5: genres.Add("Drama"); genres.Add("Soap"); genres.Add("Melodrama"); genres.Add("Folkloric"); pi.IsMovie = true; break; case 0xf6: genres.Add("Drama"); genres.Add("Romance"); break; case 0xf7: genres.Add("Drama"); genres.Add("Serious"); genres.Add("ClassicalReligion"); genres.Add("Historical"); pi.IsMovie = true; break; case 0xf8: genres.Add("Drama"); genres.Add("Adult"); pi.IsMovie = true; break; default: // unused values break; } pi.Genres = genres; } //pi.IsSeries - bool //pi.CommunityRating - float //pi.IsHD - bool //pi.IsPremiere - bool //pi.IsRepeat - bool //pi.ImagePath - string //pi.Audio - MediaBrowser.Model.LiveTv.ProgramAudio //pi.ProductionYear - int _logger.LogInformation("[TVHclient] GetEventsResponseHandler.handleResponse: add event\n{msg}\n{msg2}", currEventMessage.ToString(), createPiInfo(pi)); _result.Add(pi); } } _dataReady = true; }
public async Task <MediaSourceInfo> GetChannelStream(string channelId, string mediaSourceId, CancellationToken cancellationToken) { HTSMessage getTicketMessage = new HTSMessage(); getTicketMessage.Method = "getTicket"; getTicketMessage.putField("channelId", channelId); TaskWithTimeoutRunner <HTSMessage> twtr = new TaskWithTimeoutRunner <HTSMessage>(TIMEOUT); TaskWithTimeoutResult <HTSMessage> twtRes = await twtr.RunWithTimeout(Task.Factory.StartNew <HTSMessage>(() => { LoopBackResponseHandler lbrh = new LoopBackResponseHandler(); _htsConnectionHandler.SendMessage(getTicketMessage, lbrh); return(lbrh.getResponse()); })); if (twtRes.HasTimeout) { _logger.Error("[TVHclient] Timeout obtaining playback authentication ticket from TVH"); } else { HTSMessage getTicketResponse = twtRes.Result; if (_subscriptionId == int.MaxValue) { _subscriptionId = 0; } int currSubscriptionId = _subscriptionId++; if (_htsConnectionHandler.GetEnableSubsMaudios()) { _logger.Info("[TVHclient] Support for live TV subtitles and multiple audio tracks is enabled."); MediaSourceInfo livetvasset = new MediaSourceInfo(); livetvasset.Id = "" + currSubscriptionId; // Use HTTP basic auth instead of TVH ticketing system for authentication to allow the users to switch subs or audio tracks at any time livetvasset.Path = _htsConnectionHandler.GetHttpBaseUrl() + getTicketResponse.getString("path"); livetvasset.Protocol = MediaProtocol.Http; // Probe the asset stream to determine available sub-streams string livetvasset_probeUrl = "" + livetvasset.Path; string livetvasset_source = "LiveTV"; // Probe the asset stream to determine available sub-streams await ProbeStream(livetvasset, livetvasset_probeUrl, livetvasset_source, cancellationToken); return(livetvasset); } else { return(new MediaSourceInfo { Id = "" + currSubscriptionId, Path = _htsConnectionHandler.GetHttpBaseUrl() + getTicketResponse.getString("path") + "?ticket=" + getTicketResponse.getString("ticket"), Protocol = MediaProtocol.Http, 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, // Set to true if unknown to enable deinterlacing IsInterlaced = true }, 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 } } }); } } throw new TimeoutException(""); }