Exemple #1
0
        public override void Process()
        {
            TimeSpan ts = DateTime.Now - _updateTimer;

            if (ts.TotalMilliseconds < 500)
            {
                return;
            }
            _updateTimer = DateTime.Now;

            LiveStream _livestream = PluginMain.Navigator.LiveStream;

            if (_livestream != null && g_Player.Playing)
            {
                ServiceTuning _serviceTuning = ControlAgent.GetLiveStreamTuningDetails(_livestream);
                GUIPropertyManager.SetProperty("#TV.TuningDetails.SignalLevel.value", _serviceTuning.SignalStrength.ToString());
                GUIPropertyManager.SetProperty("#TV.TuningDetails.SignalQuality.value", _serviceTuning.SignalQuality.ToString());
                _livestream = null;
            }
        }
        public override ServiceTuning GetLiveStreamTuningDetails(LiveStream liveStream)
        {
            ServiceTuning result = null;

            lock (_liveStreamsLock)
            {
                if (_liveStreams.ContainsKey(liveStream.RtspUrl))
                {
                    IUser tve3User = _liveStreamUsers[liveStream.RtspUrl];

                    IChannel channel = TvServerPlugin.TvController_CurrentChannel(tve3User);

                    var dvbSChannel = channel as TvLibrary.Channels.DVBSChannel;
                    if (dvbSChannel != null)
                    {
                        result = new ServiceTuning()
                        {
                            CardType           = ArgusTV.DataContracts.Tuning.CardType.DvbS,
                            Frequency          = (int)dvbSChannel.Frequency,
                            InnerFecRate       = (ArgusTV.DataContracts.Tuning.FecCodeRate)dvbSChannel.InnerFecRate,
                            Modulation         = (ArgusTV.DataContracts.Tuning.Modulation)dvbSChannel.ModulationType,
                            Name               = dvbSChannel.Name,
                            ONID               = dvbSChannel.NetworkId,
                            OrbitalPosition    = dvbSChannel.SatelliteIndex, // TODO: check if this is the right number
                            Pilot              = (ArgusTV.DataContracts.Tuning.Pilot)dvbSChannel.Pilot,
                            ProviderName       = dvbSChannel.Provider,
                            IsFreeToAir        = dvbSChannel.FreeToAir,
                            RollOff            = (ArgusTV.DataContracts.Tuning.RollOff)dvbSChannel.Rolloff,
                            SID                = dvbSChannel.ServiceId,
                            SignalPolarisation = (ArgusTV.DataContracts.Tuning.SignalPolarisation)dvbSChannel.Polarisation,
                            SymbolRate         = dvbSChannel.SymbolRate,
                            TSID               = dvbSChannel.TransportId
                        };
                    }
                    else
                    {
                        var dvbCChannel = channel as TvLibrary.Channels.DVBCChannel;
                        if (dvbCChannel != null)
                        {
                            result = new ServiceTuning()
                            {
                                CardType     = ArgusTV.DataContracts.Tuning.CardType.DvbC,
                                Frequency    = (int)dvbCChannel.Frequency,
                                Modulation   = (ArgusTV.DataContracts.Tuning.Modulation)dvbCChannel.ModulationType,
                                Name         = dvbCChannel.Name,
                                ONID         = dvbCChannel.NetworkId,
                                ProviderName = dvbCChannel.Provider,
                                IsFreeToAir  = dvbCChannel.FreeToAir,
                                SID          = dvbCChannel.ServiceId,
                                SymbolRate   = dvbCChannel.SymbolRate,
                                TSID         = dvbCChannel.TransportId
                            };
                        }
                        else
                        {
                            var dvbTChannel = channel as TvLibrary.Channels.DVBTChannel;
                            if (dvbTChannel != null)
                            {
                                result = new ServiceTuning()
                                {
                                    CardType     = ArgusTV.DataContracts.Tuning.CardType.DvbT,
                                    Frequency    = (int)dvbTChannel.Frequency,
                                    Bandwidth    = dvbTChannel.BandWidth,
                                    Name         = dvbTChannel.Name,
                                    ONID         = dvbTChannel.NetworkId,
                                    ProviderName = dvbTChannel.Provider,
                                    IsFreeToAir  = dvbTChannel.FreeToAir,
                                    SID          = dvbTChannel.ServiceId,
                                    TSID         = dvbTChannel.TransportId
                                };
                            }
                            else
                            {
                                var atscChannel = channel as TvLibrary.Channels.ATSCChannel;
                                if (atscChannel != null)
                                {
                                    result = new ServiceTuning()
                                    {
                                        CardType        = ArgusTV.DataContracts.Tuning.CardType.Atsc,
                                        Frequency       = (int)atscChannel.Frequency,
                                        MajorChannel    = atscChannel.MajorChannel,
                                        MinorChannel    = atscChannel.MinorChannel,
                                        Name            = atscChannel.Name,
                                        PhysicalChannel = atscChannel.PhysicalChannel,
                                        ProviderName    = atscChannel.Provider,
                                        IsFreeToAir     = atscChannel.FreeToAir,
                                        SID             = atscChannel.ServiceId,
                                        TSID            = atscChannel.TransportId
                                    };
                                }
                                else
                                {
                                    var analogChannel = channel as TvLibrary.Implementations.AnalogChannel;
                                    if (analogChannel != null)
                                    {
                                        result = new ServiceTuning()
                                        {
                                            CardType        = ArgusTV.DataContracts.Tuning.CardType.Analog,
                                            Frequency       = (int)analogChannel.Frequency,
                                            Name            = analogChannel.Name,
                                            IsFreeToAir     = analogChannel.FreeToAir,
                                            PhysicalChannel = analogChannel.ChannelNumber
                                        };
                                    }
                                    else
                                    {
                                        var dvbIPChannel = channel as TvLibrary.Channels.DVBIPChannel;
                                        if (dvbIPChannel != null)
                                        {
                                            result = new ServiceTuning()
                                            {
                                                CardType     = ArgusTV.DataContracts.Tuning.CardType.DvbIP,
                                                Url          = dvbIPChannel.Url,
                                                Name         = dvbIPChannel.Name,
                                                ProviderName = dvbIPChannel.Provider,
                                                IsFreeToAir  = dvbIPChannel.FreeToAir
                                            };
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (result != null)
                    {
                        result.SignalQuality  = TvServerPlugin.TvController_SignalQuality(tve3User.CardId);
                        result.SignalStrength = TvServerPlugin.TvController_SignalLevel(tve3User.CardId);
                    }
                }
            }

            return(result);
        }
Exemple #3
0
        protected override void OnPageLoad()
        {
            base.OnPageLoad();

            if (!g_Player.Playing || !g_Player.IsTV)
            {
                GUIWindowManager.CloseCurrentWindow();
                return;
            }

            g_Player.PlayBackStopped += new global::MediaPortal.Player.g_Player.StoppedHandler(OnPlayBackStopped);
            g_Player.PlayBackEnded   += new global::MediaPortal.Player.g_Player.EndedHandler(OnPlayBackEnded);
            g_Player.PlayBackChanged += new global::MediaPortal.Player.g_Player.ChangedHandler(OnPlayBackChanged);

            LiveStream _livestream = PluginMain.Navigator.LiveStream;
            Channel    _channel    = PluginMain.Navigator.CurrentChannel;

            if (g_Player.Playing && g_Player.IsTV && _livestream != null && _channel != null &&
                PluginMain.IsConnected())
            {
                ServiceTuning _serviceTuning = ControlAgent.GetLiveStreamTuningDetails(_livestream);

                if (_livestream.RtspUrl.StartsWith("rtsp://", StringComparison.CurrentCultureIgnoreCase))
                {
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.RTSPURL.value", _livestream.RtspUrl);
                }
                else
                {
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.RTSPURL.value", Utility.GetLocalizedText(TextId.UnavailableText));
                }


                if (g_Player.CurrentFile.StartsWith("rtsp:", StringComparison.InvariantCultureIgnoreCase))
                {
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.StreamingMode.value", "RTSP");
                }
                else
                {
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.StreamingMode.value", "UNC");
                }


                if (g_Player.EnableSubtitle)
                {
                    if ((g_Player.SubtitleStreams > 0 /*|| g_Player.SupportsCC*/) && g_Player.CurrentSubtitleStream >= 0)
                    {
                        GUIPropertyManager.SetProperty("#TV.TuningDetails.SubtitleStream.value", g_Player.SubtitleLanguage(g_Player.CurrentSubtitleStream));
                    }
                    else
                    {
                        GUIPropertyManager.SetProperty("#TV.TuningDetails.SubtitleStream.value", Utility.GetLocalizedText(TextId.UnavailableText));
                    }
                }
                else
                {
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.SubtitleStream.value", Utility.GetLocalizedText(TextId.Off));
                }


                GUIPropertyManager.SetProperty("#TV.TuningDetails.RTSPURL.label", "RTSP URL");
                GUIPropertyManager.SetProperty("#TV.TuningDetails.SubtitleStream.label", Utility.GetLocalizedText(TextId.CurrentSubtitle));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.StreamingMode.label", Utility.GetLocalizedText(TextId.StreamingMode));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.AudioType.label", Utility.GetLocalizedText(TextId.AudioType));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.AudioType.value", g_Player.AudioType(g_Player.CurrentAudioStream));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.AudioLanguage.label", Utility.GetLocalizedText(TextId.AudioLanguage));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.AudioLanguage.value", g_Player.AudioLanguage(g_Player.CurrentAudioStream));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.VideoResolution.label", Utility.GetLocalizedText(TextId.VideoResolution));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.VideoResolution.value", g_Player.Width.ToString() + "x" + g_Player.Height.ToString());
                GUIPropertyManager.SetProperty("#TV.TuningDetails.ChannelName.label", Utility.GetLocalizedText(TextId.Channel));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.ChannelName.value", _serviceTuning.Name);
                GUIPropertyManager.SetProperty("#TV.TuningDetails.Frequency.label", Utility.GetLocalizedText(TextId.Frequency));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.Frequency.value", _serviceTuning.Frequency.ToString());
                GUIPropertyManager.SetProperty("#TV.TuningDetails.Provider.label", Utility.GetLocalizedText(TextId.Provider));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.Provider.value", _serviceTuning.ProviderName);
                GUIPropertyManager.SetProperty("#TV.TuningDetails.ChannelType.label", Utility.GetLocalizedText(TextId.Type));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.SignalLevel.label", Utility.GetLocalizedText(TextId.SignalLevel));
                GUIPropertyManager.SetProperty("#TV.TuningDetails.SignalQuality.label", Utility.GetLocalizedText(TextId.SignalQuality));

                switch (_serviceTuning.CardType)
                {
                case CardType.Analog:
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.ChannelType.value", "Analog");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Provider.value", Utility.GetLocalizedText(TextId.Unknown));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.value", "");
                    break;

                case CardType.Atsc:
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.ChannelType.value", "ATSC");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Provider.value", Utility.GetLocalizedText(TextId.Unknown));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.label", Utility.GetLocalizedText(TextId.Encrypted));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.value", _serviceTuning.IsFreeToAir ? Utility.GetLocalizedText(TextId.No) : Utility.GetLocalizedText(TextId.Yes));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.label", Utility.GetLocalizedText(TextId.Modulation));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.value", _serviceTuning.Modulation.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.label", "Symbol Rate");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.value", _serviceTuning.SymbolRate.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.label", "Service ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.value", _serviceTuning.SID.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.label", "Transport ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.value", _serviceTuning.TSID.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.label", "InnerFecRate");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.value", _serviceTuning.InnerFecRate.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.label", "Physical Channel");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.value", _serviceTuning.PhysicalChannel.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.value", "");
                    break;

                case CardType.DvbC:
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.ChannelType.value", "DVB-C");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.label", Utility.GetLocalizedText(TextId.Encrypted));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.value", _serviceTuning.IsFreeToAir ? Utility.GetLocalizedText(TextId.No) : Utility.GetLocalizedText(TextId.Yes));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.label", Utility.GetLocalizedText(TextId.Modulation));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.value", _serviceTuning.Modulation.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.label", "Symbol Rate");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.value", _serviceTuning.SymbolRate.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.label", "Service ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.value", _serviceTuning.SID.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.label", "Network ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.value", _serviceTuning.ONID.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.label", "Transport ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.value", _serviceTuning.TSID.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.label", "InnerFecRate");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.value", _serviceTuning.InnerFecRate.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.label", "OuterFecRate");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.value", _serviceTuning.OuterFecRate.ToString());
                    break;

                case CardType.DvbS:
                    if (_serviceTuning.IsDvbS2)
                    {
                        GUIPropertyManager.SetProperty("#TV.TuningDetails.ChannelType.value", "DVB-S2");
                    }
                    else
                    {
                        GUIPropertyManager.SetProperty("#TV.TuningDetails.ChannelType.value", "DVB-S");
                    }

                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.label", Utility.GetLocalizedText(TextId.SatellitePosition));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.value", _serviceTuning.OrbitalPosition.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.label", Utility.GetLocalizedText(TextId.Encrypted));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.value", _serviceTuning.IsFreeToAir ? Utility.GetLocalizedText(TextId.No) : Utility.GetLocalizedText(TextId.Yes));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.label", Utility.GetLocalizedText(TextId.Modulation));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.value", _serviceTuning.Modulation.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.label", Utility.GetLocalizedText(TextId.Polarisation));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.value", _serviceTuning.SignalPolarisation.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.label", "Symbol Rate");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.value", _serviceTuning.SymbolRate.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.label", "Service ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.value", _serviceTuning.SID.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.label", "Network ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.value", _serviceTuning.ONID.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.label", "Transport ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.value", _serviceTuning.TSID.ToString());
                    break;

                case CardType.DvbT:
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.ChannelType.value", "DVB-T");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.label", Utility.GetLocalizedText(TextId.Encrypted));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.value", _serviceTuning.IsFreeToAir ? Utility.GetLocalizedText(TextId.No) : Utility.GetLocalizedText(TextId.Yes));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.label", Utility.GetLocalizedText(TextId.Modulation));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.value", _serviceTuning.Modulation.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.label", Utility.GetLocalizedText(TextId.Bandwidth));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.value", _serviceTuning.Bandwidth.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.label", "Service ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.value", _serviceTuning.SID.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.label", "Network ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.value", _serviceTuning.ONID.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.label", "Transport ID");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.value", _serviceTuning.TSID.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.label", "InnerFecRate");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.value", _serviceTuning.InnerFecRate.ToString());
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.label", Utility.GetLocalizedText(TextId.TransmissionMode));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.value", _serviceTuning.TransmissionMode.ToString());
                    break;

                default:
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.ChannelType.value", Utility.GetLocalizedText(TextId.Unknown));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Provider.value", Utility.GetLocalizedText(TextId.Unknown));
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail1.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail2.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail3.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail4.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail5.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail6.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail7.value", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.label", "");
                    GUIPropertyManager.SetProperty("#TV.TuningDetails.Detail8.value", "");
                    break;
                }
            }
        }
Exemple #4
0
        public RecorderModule()
            : base("Recorder")
        {
            this.OnError.AddItemToStartOfPipeline((context, ex) =>
            {
                EventLogger.WriteEntry(ex);
                return(null);
            });

            // Ping Recorder service.
            //
            // Returns the version of the API on the recorder, which should be Constants.RecorderApiVersion.
            Get["/Ping"] = p =>
            {
                int result = -1;
                _staContext.Send((s) => { result = Service.Ping(); }, null);
                return(new
                {
                    result = Constants.RecorderApiVersion
                });
            };

            // Get the server's MAC address(es).  These can be stored on the client after a successful
            // connect and later used to re-connect with wake-on-lan.
            //
            // Returns an array containing one or more MAC addresses in HEX string format (e.g. "A1B2C3D4E5F6").
            Get["/MacAddresses"] = p =>
            {
                List <String> result = null;
                _staContext.Send((s) => { result = Service.GetMacAddresses(); }, null);
                return(new
                {
                    result = result
                });
            };

            // Ask the recorder to initialize by registering itself over the Recorder callback's
            // RegisterRecorder method.
            //
            // recorderId - The unique ID of this recorder.
            //
            // Post-data is an object with:
            //   schedulerBaseUrl - The callback URL for the Recorder to communicate with the Scheduler.
            Put["/Initialize/{recorderId}"] = p =>
            {
                var args = this.Bind <InitializeArguments>();

                _staContext.Send((s) => { Service.Initialize(p.recorderId, args.schedulerBaseUrl); }, null);
                return(HttpStatusCode.OK);
            };

            // Ask the recorder to allocate a (virtual) card for a channel.  The previously allocated
            // cards are also passed in, so the implementation must take into account that these cards
            // are no longer available when this call is made.  Note that the implementation must *not*
            // worry about cards being actually free at the moment the call is made!  This is purely a
            // theoretical calculation that is used by ARGUS TV to manage its upcoming recordings.
            //
            //   channel - The channel to allocate.
            //   alreadyAllocated - All previously allocated channels/cards.
            //   useReversePriority - Use reverse cards priority to avoid conflicts with live streaming.
            //
            // Returns the unique card ID of the card that can record this channel, or null if no free card was found.
            Put["/AllocateCard"] = p =>
            {
                var args = this.Bind <AllocateCardArguments>();

                string result = null;
                _staContext.Send((s) => { result = Service.AllocateCard(args.channel, args.alreadyAllocated, args.useReversePriority); }, null);
                return(new
                {
                    result = result
                });
            };

            // Tell the recorder to actually start a recording on the given card.  The implementation
            // must call /NewRecording on the Recorder callback service when the recording actually
            // starts.  If the recording can't start for some reason /Recording/StartFailed must be called.
            // In case the recording ends (prematurely or on time) /EndRecording must be called.
            // IMPORTANT: If the suggested relative path and filename was used the recorder should
            // return 'false' to /EndRecording's 'okToMoveFile'!
            //
            // Post-data is an object with:
            //   schedulerBaseUrl - The callback URL for the Recorder to communicate with the Scheduler.
            //   channelAllocation - The card allocation for the channel.
            //   startTimeUtc - The actual time to start the recording (UTC).
            //   stopTimeUtc - The actual time to stop the recording (UTC).
            //   recordingProgram - The program to record.
            //   suggestedBaseFileName - The suggested relative path and filename (without extension) of the recording file.
            //
            // Returns a boolean indicating the recording was initiated succesfully.
            Post["/Recording/Start"] = p =>
            {
                var args = this.Bind <StartRecordingArguments>();

                bool result = false;
                _staContext.Send((s) => { result = Service.StartRecording(args.schedulerBaseUrl, args.channelAllocation, args.startTimeUtc, args.stopTimeUtc, args.recordingProgram, args.suggestedBaseFileName); }, null);
                return(new
                {
                    result = result
                });
            };

            // Validate a recording is still running, and update its actual stop time.
            //
            // Post-data is an object with:
            //   channelAllocation - The card allocation for the channel.
            //   recordingProgram - The program being recorded.
            //   stopTimeUtc - The up-to-date stop time (UTC).
            //
            // Returns true if the recording was still running (and its stop time was succesfully updated), false if there was a problem or the recording is not running.
            Put["/Recording/ValidateAndUpdate"] = p =>
            {
                var args = this.Bind <ValidateAndUpdateRecordingArguments>();

                bool result = false;
                _staContext.Send((s) => { result = Service.ValidateAndUpdateRecording(args.channelAllocation, args.recordingProgram, args.stopTimeUtc); }, null);
                return(new
                {
                    result = result
                });
            };

            // Tell the recorder to abort the recording of a program.  The implementation must call
            // EndRecording() on the Recorder callback service.
            //
            // Post-data is an object with:
            //   schedulerBaseUrl - The callback URL for the Recorder to communicate with the Scheduler.
            //   recordingProgram - The program being recorded.
            //
            // Returns true if the recording was found and aborted.
            Put["/Recording/Abort"] = p =>
            {
                var args = this.Bind <AbortRecordingArguments>();

                bool result = false;
                _staContext.Send((s) => { result = Service.AbortRecording(args.schedulerBaseUrl, args.recordingProgram); }, null);
                return(new
                {
                    result = result
                });
            };

            // Retrieves the recording shares of the recorder.
            Get["/RecordingShares"] = p =>
            {
                List <string> result = null;
                _staContext.Send((s) => { result = Service.GetRecordingShares(); }, null);
                return(new
                {
                    result = result
                });
            };

            // Retrieves the timeshift shares of the recorder.
            Get["/TimeshiftShares"] = p =>
            {
                List <string> result = null;
                _staContext.Send((s) => { result = Service.GetTimeshiftShares(); }, null);
                return(new
                {
                    result = result
                });
            };

            #region Live Streaming

            // Tune to a channel, and get a live stream to that channel.
            //
            // Post-data is an object with:
            //   channel - The channel to tune to.
            //   upcomingRecordingAllocation - The allocation of the next upcoming recording, or null if there isn't one.
            //   stream - The live stream in case of retuning an existing stream, or null for a new one.
            //
            // Returns a LiveStreamResult value to indicate success or failure.
            Post["/Live/Tune"] = p =>
            {
                var args   = this.Bind <TuneLiveStreamArguments>();
                var stream = args.stream;

                LiveStreamResult result = LiveStreamResult.UnknownError;
                _staContext.Send((s) => { result = Service.TuneLiveStream(args.channel, args.upcomingRecordingAllocation, ref stream); }, null);
                return(new
                {
                    result = result,
                    stream = stream
                });
            };

            // Tell the recorder we are still showing this stream and to keep it alive. Call this every 30 seconds or so.
            //
            // Post-data is the live stream that is stil in use.
            //
            // Returns true if the live stream is still running, false otherwise.
            Put["/Live/KeepAlive"] = p =>
            {
                var stream = this.Bind <LiveStream>();

                bool result = false;
                _staContext.Send((s) => { result = Service.KeepLiveStreamAlive(stream); }, null);
                return(new
                {
                    result = result
                });
            };

            // Stop the live stream (if it is found and belongs to the recorder).
            //
            // Post-data is the live stream to stop.
            Put["/Live/Stop"] = p =>
            {
                var stream = this.Bind <LiveStream>();
                _staContext.Send((s) => { Service.StopLiveStream(stream); }, null);
                return(HttpStatusCode.OK);
            };

            // Get all live streams.
            Get["/LiveStreams"] = p =>
            {
                return(new
                {
                    result = Service.GetLiveStreams()
                });
            };

            // Get the live tuning state of a number of channels.
            //
            // Post-data is an object with:
            //   channels - The channels to get the live state from.
            //   stream - The live stream you want to be ignored (since it's yours), or null.
            //
            // Returns an array with all the live states for the given channels.
            Put["/ChannelsLiveState"] = p =>
            {
                var args = this.Bind <GetChannelsLiveStateArguments>();

                return(new
                {
                    result = Service.GetChannelsLiveState(args.channels, args.stream)
                });
            };

            // Ask the recorder for the give live stream's tuning details (if possible).
            //
            // Post-data is the active live stream.
            //
            // Returns the service tuning details, or null if none are available.
            Put["/Live/TuningDetails"] = p =>
            {
                var stream = this.Bind <LiveStream>();

                ServiceTuning result = null;
                _staContext.Send((s) => { result = Service.GetLiveStreamTuningDetails(stream); }, null);
                return(new
                {
                    result = result
                });
            };

            #endregion

            #region Teletext

            // Ask the recorder whether the given liveStream has teletext.
            //
            // Post-data is the live stream.
            //
            // Returns true if teletext is present.
            Put["/Live/HasTeletext"] = p =>
            {
                var stream = this.Bind <LiveStream>();

                bool result = false;
                _staContext.Send((s) => { result = Service.HasTeletext(stream); }, null);
                return(new
                {
                    result = result
                });
            };

            // Tell the recorder to start grabbing teletext for the given live stream.
            //
            // Post-data is the live stream.
            Put["/Live/Teletext/StartGrabbing"] = p =>
            {
                var stream = this.Bind <LiveStream>();

                _staContext.Send((s) => { Service.StartGrabbingTeletext(stream); }, null);
                return(HttpStatusCode.OK);
            };

            // Tell the recorder to stop grabbing teletext for the given live stream.
            //
            // Post-data is the live stream.
            Put["/Live/Teletext/StopGrabbing"] = p =>
            {
                var stream = this.Bind <LiveStream>();

                _staContext.Send((s) => { Service.StopGrabbingTeletext(stream); }, null);
                return(HttpStatusCode.OK);
            };

            // Tell the recorder to start grabbing teletext for the given live stream.
            //
            // Post-data is the live stream.
            //
            // Returns true if the recorder is grabbing teletext.
            Put["/Live/Teletext/IsGrabbing"] = p =>
            {
                var stream = this.Bind <LiveStream>();

                bool result = false;
                _staContext.Send((s) => { result = Service.IsGrabbingTeletext(stream); }, null);
                return(new
                {
                    result = result
                });
            };

            // Request a teletext page/subpage from the recorder for the given live stream.
            //
            // pageNumber - The teletext page number.
            // subPageNumber - The teletext subpage number.
            //
            // Post-data is the live stream.
            //
            // Returns an object with:
            //   result - The requested page content (base64-encoded), or null if the page was not ready yet.
            //   subPageCount - The total number of subpages of this page.
            Put["/Live/Teletext/GetPage/{pageNumber}/{subPageNumber}"] = p =>
            {
                var stream = this.Bind <LiveStream>();

                int    subPageCount = 0;
                byte[] result       = null;
                _staContext.Send((s) => { result = Service.GetTeletextPageBytes(stream, p.pageNumber, p.subPageNumber, out subPageCount); }, null);
                return(new
                {
                    result = result == null ? null : Convert.ToBase64String(result, Base64FormattingOptions.None),
                    subPageCount = subPageCount
                });
            };

            #endregion
        }