コード例 #1
0
        public async Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken)
        {
            int timeOut = await WaitForInitialLoadTask(cancellationToken);

            if (timeOut == -1 || cancellationToken.IsCancellationRequested)
            {
                _logger.LogInformation("[TVHclient] CreateTimerAsync, call canceled or timed out.");
                return;
            }

            HTSMessage createTimerMessage = new HTSMessage();

            createTimerMessage.Method = "addDvrEntry";
            createTimerMessage.putField("channelId", info.ChannelId);
            createTimerMessage.putField("start", DateTimeHelper.getUnixUTCTimeFromUtcDateTime(info.StartDate));
            createTimerMessage.putField("stop", DateTimeHelper.getUnixUTCTimeFromUtcDateTime(info.EndDate));
            createTimerMessage.putField("startExtra", (long)(info.PrePaddingSeconds / 60));
            createTimerMessage.putField("stopExtra", (long)(info.PostPaddingSeconds / 60));
            createTimerMessage.putField("priority", _htsConnectionHandler.GetPriority()); // info.Priority delivers always 0 - no GUI
            createTimerMessage.putField("configName", _htsConnectionHandler.GetProfile());
            createTimerMessage.putField("description", info.Overview);
            createTimerMessage.putField("title", info.Name);
            createTimerMessage.putField("creator", Plugin.Instance.Configuration.Username);

            TaskWithTimeoutRunner <HTSMessage> twtr   = new TaskWithTimeoutRunner <HTSMessage>(TIMEOUT);
            TaskWithTimeoutResult <HTSMessage> twtRes = await twtr.RunWithTimeout(Task.Factory.StartNew <HTSMessage>(() =>
            {
                LoopBackResponseHandler lbrh = new LoopBackResponseHandler();
                _htsConnectionHandler.SendMessage(createTimerMessage, lbrh);
                return(lbrh.getResponse());
            }));

            if (twtRes.HasTimeout)
            {
                _logger.LogError("[TVHclient] Can't create timer because of timeout");
            }
            else
            {
                HTSMessage createTimerResponse = twtRes.Result;
                Boolean    success             = createTimerResponse.getInt("success", 0) == 1;
                if (!success)
                {
                    if (createTimerResponse.containsField("error"))
                    {
                        _logger.LogError("[TVHclient] Can't create timer: '{why}'", createTimerResponse.getString("error"));
                    }
                    else if (createTimerResponse.containsField("noaccess"))
                    {
                        _logger.LogError("[TVHclient] Can't create timer: '{why}'", createTimerResponse.getString("noaccess"));
                    }
                }
            }
        }
コード例 #2
0
        public async Task UpdateTimerAsync(TimerInfo info, CancellationToken cancellationToken)
        {
            int timeOut = await WaitForInitialLoadTask(cancellationToken);

            if (timeOut == -1 || cancellationToken.IsCancellationRequested)
            {
                _logger.LogInformation("[TVHclient] UpdateTimerAsync, call canceled or timed out.");
                return;
            }

            HTSMessage updateTimerMessage = new HTSMessage();

            updateTimerMessage.Method = "updateDvrEntry";
            updateTimerMessage.putField("id", info.Id);
            updateTimerMessage.putField("startExtra", (long)(info.PrePaddingSeconds / 60));
            updateTimerMessage.putField("stopExtra", (long)(info.PostPaddingSeconds / 60));

            TaskWithTimeoutRunner <HTSMessage> twtr   = new TaskWithTimeoutRunner <HTSMessage>(TIMEOUT);
            TaskWithTimeoutResult <HTSMessage> twtRes = await twtr.RunWithTimeout(Task.Factory.StartNew <HTSMessage>(() =>
            {
                LoopBackResponseHandler lbrh = new LoopBackResponseHandler();
                _htsConnectionHandler.SendMessage(updateTimerMessage, lbrh);
                LastRecordingChange = DateTime.UtcNow;
                return(lbrh.getResponse());
            }));

            if (twtRes.HasTimeout)
            {
                _logger.LogError("[TVHclient] Can't update timer because of timeout");
            }
            else
            {
                HTSMessage updateTimerResponse = twtRes.Result;
                Boolean    success             = updateTimerResponse.getInt("success", 0) == 1;
                if (!success)
                {
                    if (updateTimerResponse.containsField("error"))
                    {
                        _logger.LogError("[TVHclient] Can't update timer: '{why}'", updateTimerResponse.getString("error"));
                    }
                    else if (updateTimerResponse.containsField("noaccess"))
                    {
                        _logger.LogError("[TVHclient] Can't update timer: '{why}'", updateTimerResponse.getString("noaccess"));
                    }
                }
            }
        }
コード例 #3
0
        public async Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken)
        {
            int timeOut = await WaitForInitialLoadTask(cancellationToken);

            if (timeOut == -1 || cancellationToken.IsCancellationRequested)
            {
                _logger.Info("[TVHclient] DeleteRecordingAsync, call canceled or timed out.");
                return;
            }

            HTSMessage deleteRecordingMessage = new HTSMessage();

            deleteRecordingMessage.Method = "deleteDvrEntry";
            deleteRecordingMessage.putField("id", recordingId);

            TaskWithTimeoutRunner <HTSMessage> twtr   = new TaskWithTimeoutRunner <HTSMessage>(TIMEOUT);
            TaskWithTimeoutResult <HTSMessage> twtRes = await twtr.RunWithTimeout(Task.Factory.StartNew <HTSMessage>(() =>
            {
                LoopBackResponseHandler lbrh = new LoopBackResponseHandler();
                _htsConnectionHandler.SendMessage(deleteRecordingMessage, lbrh);
                LastRecordingChange = DateTimeOffset.UtcNow;
                return(lbrh.getResponse());
            }));

            if (twtRes.HasTimeout)
            {
                _logger.Error("[TVHclient] Can't delete recording because of timeout");
            }
            else
            {
                HTSMessage deleteRecordingResponse = twtRes.Result;
                Boolean    success = deleteRecordingResponse.getInt("success", 0) == 1;
                if (!success)
                {
                    if (deleteRecordingResponse.containsField("error"))
                    {
                        _logger.Error("[TVHclient] Can't delete recording: '" + deleteRecordingResponse.getString("error") + "'");
                    }
                    else if (deleteRecordingResponse.containsField("noaccess"))
                    {
                        _logger.Error("[TVHclient] Can't delete recording: '" + deleteRecordingResponse.getString("noaccess") + "'");
                    }
                }
            }
        }
コード例 #4
0
        public void dvrEntryDelete(HTSMessage message)
        {
            string id = message.getString("id");

            lock (_data)
            {
                _data.Remove(id);
            }
        }
コード例 #5
0
        public void dvrEntryAdd(HTSMessage message)
        {
            string id = message.getString("id");

            lock (_data)
            {
                if (_data.ContainsKey(id))
                {
                    _logger.Info("[TVHclient] DvrDataHelper.dvrEntryAdd id already in database - skip!" + message.ToString());
                    return;
                }
                _data.Add(id, message);
            }
        }
コード例 #6
0
        public void autorecEntryAdd(HTSMessage message)
        {
            string id = message.getString("id");

            lock (_data)
            {
                if (_data.ContainsKey(id))
                {
                    _logger.LogDebug("[TVHclient] AutorecDataHelper.autorecEntryAdd: id already in database - skipping");
                    return;
                }
                _data.Add(id, message);
            }
        }
コード例 #7
0
        /// <summary>
        /// Cancel the Series Timer
        /// </summary>
        /// <param name="timerId">The Timer Id</param>
        /// <param name="cancellationToken">The CancellationToken</param>
        /// <returns></returns>
        public async Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken)
        {
            ensureConnection();

            int timeOut = await WaitForInitialLoadTask(cancellationToken);

            if (timeOut == -1 || cancellationToken.IsCancellationRequested)
            {
                _logger.Info("[TVHclient] CancelSeriesTimerAsync, call canceled or timed out.");
                return;
            }

            HTSMessage deleteAutorecMessage = new HTSMessage();

            deleteAutorecMessage.Method = "deleteAutorecEntry";
            deleteAutorecMessage.putField("id", timerId);

            //HTSMessage deleteAutorecResponse = await Task.Factory.StartNew<HTSMessage>(() =>
            //{
            //    LoopBackResponseHandler lbrh = new LoopBackResponseHandler();
            //    _htsConnection.sendMessage(deleteAutorecMessage, 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(deleteAutorecMessage, lbrh);
                return(lbrh.getResponse());
            }));

            if (twtRes.HasTimeout)
            {
                _logger.Error("[TVHclient] Can't delete recording because of timeout");
            }
            else
            {
                HTSMessage deleteAutorecResponse = twtRes.Result;
                Boolean    success = deleteAutorecResponse.getInt("success", 0) == 1;
                if (!success)
                {
                    _logger.Error("[TVHclient] Can't cancel timer: '" + deleteAutorecResponse.getString("error") + "'");
                }
            }
        }
コード例 #8
0
        public void autorecEntryUpdate(HTSMessage message)
        {
            string id = message.getString("id");

            lock (_data)
            {
                HTSMessage oldMessage = _data[id];
                if (oldMessage == null)
                {
                    _logger.LogDebug("[TVHclient] AutorecDataHelper.autorecEntryAdd: id not in database - skipping");
                    return;
                }
                foreach (KeyValuePair <string, object> entry in message)
                {
                    if (oldMessage.containsField(entry.Key))
                    {
                        oldMessage.removeField(entry.Key);
                    }
                    oldMessage.putField(entry.Key, entry.Value);
                }
            }
        }
コード例 #9
0
        public void dvrEntryUpdate(HTSMessage message)
        {
            string id = message.getString("id");

            lock (_data)
            {
                HTSMessage oldMessage = _data[id];
                if (oldMessage == null)
                {
                    _logger.Info("[TVHclient] DvrDataHelper.dvrEntryUpdate id not in database - skip!" + message.ToString());
                    return;
                }
                foreach (KeyValuePair <string, object> entry in message)
                {
                    if (oldMessage.containsField(entry.Key))
                    {
                        oldMessage.removeField(entry.Key);
                    }
                    oldMessage.putField(entry.Key, entry.Value);
                }
            }
        }
コード例 #10
0
        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;
                }
            }));
        }
コード例 #11
0
        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;
                }
            }));
        }
コード例 #12
0
        public async Task CancelTimerAsync(string timerId, CancellationToken cancellationToken)
        {
            int timeOut = await WaitForInitialLoadTask(cancellationToken);

            if (timeOut == -1 || cancellationToken.IsCancellationRequested)
            {
                _logger.LogDebug("[TVHclient] LiveTvService.CancelTimerAsync: call cancelled or timed out");
                return;
            }

            HTSMessage cancelTimerMessage = new HTSMessage();

            cancelTimerMessage.Method = "cancelDvrEntry";
            cancelTimerMessage.putField("id", timerId);

            TaskWithTimeoutRunner <HTSMessage> twtr   = new TaskWithTimeoutRunner <HTSMessage>(TIMEOUT);
            TaskWithTimeoutResult <HTSMessage> twtRes = await twtr.RunWithTimeout(Task.Factory.StartNew <HTSMessage>(() =>
            {
                LoopBackResponseHandler lbrh = new LoopBackResponseHandler();
                _htsConnectionHandler.SendMessage(cancelTimerMessage, lbrh);
                LastRecordingChange = DateTime.UtcNow;
                return(lbrh.getResponse());
            }));

            if (twtRes.HasTimeout)
            {
                _logger.LogError("[TVHclient] LiveTvService.CancelTimerAsync: can't cancel timer because the timeout was reached");
            }
            else
            {
                HTSMessage cancelTimerResponse = twtRes.Result;
                Boolean    success             = cancelTimerResponse.getInt("success", 0) == 1;
                if (!success)
                {
                    if (cancelTimerResponse.containsField("error"))
                    {
                        _logger.LogError("[TVHclient] LiveTvService.CancelTimerAsync: can't cancel timer: '{why}'", cancelTimerResponse.getString("error"));
                    }
                    else if (cancelTimerResponse.containsField("noaccess"))
                    {
                        _logger.LogError("[TVHclient] LiveTvService.CancelTimerAsync: can't cancel timer: '{why}'", cancelTimerResponse.getString("noaccess"));
                    }
                }
            }
        }
コード例 #13
0
        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;
                }
            }));
        }
コード例 #14
0
        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;
                }
            }));
        }
コード例 #15
0
        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();
        }
コード例 #16
0
        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();
        }
コード例 #17
0
        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;
                }
            }));
        }
コード例 #18
0
        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;
                }
            }));
        }
コード例 #19
0
        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("");
        }
コード例 #20
0
        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;
                }
            }));
        }
コード例 #21
0
        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);
        }