/// <summary>
        /// Creates a MediaItem that represents a TV stream. The MediaItem also holds information about stream indices to provide PiP
        /// functions (<paramref name="slotIndex"/>).
        /// </summary>
        /// <param name="slotIndex">Index of the slot (0/1)</param>
        /// <param name="path">Path or URL of the stream</param>
        /// <param name="channel"></param>
        /// <returns></returns>
        public static LiveTvMediaItem CreateMediaItem(int slotIndex, string path, IChannel channel)
        {
            if (!String.IsNullOrEmpty(path))
            {
                ISystemResolver systemResolver = ServiceRegistration.Get <ISystemResolver>();
                IDictionary <Guid, MediaItemAspect> aspects = new Dictionary <Guid, MediaItemAspect>();
                MediaItemAspect providerResourceAspect;
                MediaItemAspect mediaAspect;

                SlimTvResourceAccessor resourceAccessor = new SlimTvResourceAccessor(slotIndex, path);
                aspects[ProviderResourceAspect.ASPECT_ID] = providerResourceAspect = new MediaItemAspect(ProviderResourceAspect.Metadata);
                aspects[MediaAspect.ASPECT_ID]            = mediaAspect = new MediaItemAspect(MediaAspect.Metadata);
                // VideoAspect needs to be included to associate VideoPlayer later!
                aspects[VideoAspect.ASPECT_ID] = new MediaItemAspect(VideoAspect.Metadata);
                providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, systemResolver.LocalSystemId);

                String raPath = resourceAccessor.CanonicalLocalResourcePath.Serialize();
                providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, raPath);

                mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, "Live TV");
                mediaAspect.SetAttribute(MediaAspect.ATTR_MIME_TYPE, "video/livetv"); // Custom mimetype for LiveTv

                LiveTvMediaItem tvStream = new LiveTvMediaItem(new Guid(), aspects);

                tvStream.AdditionalProperties[LiveTvMediaItem.SLOT_INDEX]  = slotIndex;
                tvStream.AdditionalProperties[LiveTvMediaItem.CHANNEL]     = channel;
                tvStream.AdditionalProperties[LiveTvMediaItem.TUNING_TIME] = DateTime.Now;
                return(tvStream);
            }
            return(null);
        }
Exemple #2
0
        private void UpdateExistingMediaItem(MediaItem timeshiftMediaItem)
        {
            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();

            for (int index = 0; index < playerContextManager.NumActivePlayerContexts; index++)
            {
                IPlayerContext playerContext = playerContextManager.GetPlayerContext(index);
                if (playerContext == null)
                {
                    continue;
                }
                LiveTvMediaItem liveTvMediaItem    = playerContext.CurrentMediaItem as LiveTvMediaItem;
                LiveTvMediaItem newLiveTvMediaItem = timeshiftMediaItem as LiveTvMediaItem;
                // Check if this is "our" media item to update.
                if (liveTvMediaItem == null || newLiveTvMediaItem == null || !IsSameSlot(liveTvMediaItem, newLiveTvMediaItem))
                {
                    continue;
                }

                if (!IsSameLiveTvItem(liveTvMediaItem, newLiveTvMediaItem))
                {
                    // Switch MediaItem in current slot, the LiveTvPlayer implements IReusablePlayer and will change its source without need to change full player.
                    playerContext.DoPlay(newLiveTvMediaItem);
                    // Copy old channel history into new item
                    liveTvMediaItem.TimeshiftContexes.ToList().ForEach(tc => newLiveTvMediaItem.TimeshiftContexes.Add(tc));
                    // Use new MediaItem, so new context will be added to new instance.
                    liveTvMediaItem = newLiveTvMediaItem;
                }
                // Add new timeshift context
                AddOrUpdateTimeshiftContext(liveTvMediaItem, newLiveTvMediaItem.AdditionalProperties[LiveTvMediaItem.CHANNEL] as IChannel);
            }
        }
Exemple #3
0
        /// <summary>
        /// Checks if both <see cref="LiveTvMediaItem"/> are of same type, which includes mimeType and streaming url. This check is used to detected
        /// card changes on server and switching between radio and tv channels.
        /// </summary>
        /// <param name="oldItem"></param>
        /// <param name="newItem"></param>
        /// <returns></returns>
        protected bool IsSameLiveTvItem(LiveTvMediaItem oldItem, LiveTvMediaItem newItem)
        {
            string oldPath = oldItem.Aspects[ProviderResourceAspect.ASPECT_ID].GetAttributeValue(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH).ToString();
            string newPath = newItem.Aspects[ProviderResourceAspect.ASPECT_ID].GetAttributeValue(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH).ToString();

            if (oldPath != newPath)
            {
                return(false);
            }

            IChannel oldChannel = oldItem.AdditionalProperties[LiveTvMediaItem.CHANNEL] as IChannel;
            IChannel newChannel = newItem.AdditionalProperties[LiveTvMediaItem.CHANNEL] as IChannel;

            if (oldChannel != null && newChannel != null && oldChannel.MediaType != newChannel.MediaType)
            {
                return(false);
            }

            string oldMimeType;
            string oldTitle;
            string newMimeType;
            string newTitle;

            return(oldItem.GetPlayData(out oldMimeType, out oldTitle) && newItem.GetPlayData(out newMimeType, out newTitle) && oldMimeType == newMimeType);
        }
    /// <summary>
    /// Creates a MediaItem that represents a TV stream. The MediaItem also holds information about stream indices to provide PiP
    /// functions (<paramref name="slotIndex"/>).
    /// </summary>
    /// <param name="slotIndex">Index of the slot (0/1)</param>
    /// <param name="path">Path or URL of the stream</param>
    /// <param name="channel"></param>
    /// <returns></returns>
    public static LiveTvMediaItem CreateMediaItem(int slotIndex, string path, IChannel channel)
    {
      if (!String.IsNullOrEmpty(path))
      {
        ISystemResolver systemResolver = ServiceRegistration.Get<ISystemResolver>();
        IDictionary<Guid, MediaItemAspect> aspects = new Dictionary<Guid, MediaItemAspect>();
        MediaItemAspect providerResourceAspect;
        MediaItemAspect mediaAspect;

        SlimTvResourceAccessor resourceAccessor = new SlimTvResourceAccessor(slotIndex, path);
        aspects[ProviderResourceAspect.ASPECT_ID] = providerResourceAspect = new MediaItemAspect(ProviderResourceAspect.Metadata);
        aspects[MediaAspect.ASPECT_ID] = mediaAspect = new MediaItemAspect(MediaAspect.Metadata);
        // VideoAspect needs to be included to associate VideoPlayer later!
        aspects[VideoAspect.ASPECT_ID] = new MediaItemAspect(VideoAspect.Metadata);
        providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, systemResolver.LocalSystemId);

        String raPath = resourceAccessor.CanonicalLocalResourcePath.Serialize();
        providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, raPath);

        mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, "Live TV");
        mediaAspect.SetAttribute(MediaAspect.ATTR_MIME_TYPE, "video/livetv"); // Custom mimetype for LiveTv

        LiveTvMediaItem tvStream = new LiveTvMediaItem(new Guid(), aspects);

        tvStream.AdditionalProperties[LiveTvMediaItem.SLOT_INDEX] = slotIndex;
        tvStream.AdditionalProperties[LiveTvMediaItem.CHANNEL] = channel;
        tvStream.AdditionalProperties[LiveTvMediaItem.TUNING_TIME] = DateTime.Now;
        return tvStream;
      }
      return null;
    }
        private void UpdateExistingMediaItem(MediaItem timeshiftMediaItem)
        {
            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();

            for (int index = 0; index < playerContextManager.NumActivePlayerContexts; index++)
            {
                IPlayerContext playerContext = playerContextManager.GetPlayerContext(index);
                if (playerContext != null)
                {
                    LiveTvMediaItem liveTvMediaItem    = playerContext.CurrentMediaItem as LiveTvMediaItem;
                    LiveTvMediaItem newLiveTvMediaItem = timeshiftMediaItem as LiveTvMediaItem;
                    if (liveTvMediaItem != null && newLiveTvMediaItem != null)
                    {
                        // check if this is "our" media item to update.
                        if ((int)liveTvMediaItem.AdditionalProperties[LiveTvMediaItem.SLOT_INDEX] == (int)newLiveTvMediaItem.AdditionalProperties[LiveTvMediaItem.SLOT_INDEX])
                        {
                            if (liveTvMediaItem.Aspects[ProviderResourceAspect.ASPECT_ID].GetAttributeValue(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH).ToString() !=
                                newLiveTvMediaItem.Aspects[ProviderResourceAspect.ASPECT_ID].GetAttributeValue(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH).ToString())
                            {
                                //switch MediaItem in current slot
                                playerContext.DoPlay(newLiveTvMediaItem);
                                //clear former timeshift contexes (card change cause loss of buffer in rtsp mode).
                                liveTvMediaItem.TimeshiftContexes.Clear();
                            }
                            // add new timeshift context
                            AddTimeshiftContext(liveTvMediaItem, newLiveTvMediaItem.AdditionalProperties[LiveTvMediaItem.CHANNEL] as IChannel);
                        }
                    }
                }
            }
        }
Exemple #6
0
        public MediaItem CreateMediaItem(int slotIndex, string streamUrl, IChannel channel)
        {
            // Channel is usually only passed as placeholder with ID only, so query the details here
            IChannelService channelService = GlobalServiceProvider.Get <IChannelService>();
            Channel         fullChannel    = channelService.GetChannel(channel.ChannelId);

            bool            isTv     = fullChannel.MediaType == 0;
            LiveTvMediaItem tvStream = isTv
        ? SlimTvMediaItemBuilder.CreateMediaItem(slotIndex, streamUrl, fullChannel.ToChannel())
        : SlimTvMediaItemBuilder.CreateRadioMediaItem(slotIndex, streamUrl, fullChannel.ToChannel());

            if (tvStream != null)
            {
                // Add program infos to the LiveTvMediaItem
                IProgram currentProgram;
                IProgram nextProgram;
                if (GetNowNextProgram(channel, out currentProgram, out nextProgram))
                {
                    tvStream.AdditionalProperties[LiveTvMediaItem.CURRENT_PROGRAM] = currentProgram;
                    tvStream.AdditionalProperties[LiveTvMediaItem.NEXT_PROGRAM]    = nextProgram;
                }
                return(tvStream);
            }
            return(null);
        }
        private async Task <bool> InitActionsList()
        {
            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();
            IPlayerContext        playerContext        = playerContextManager.GetPlayerContext(PlayerChoice.PrimaryPlayer);

            if (playerContext == null)
            {
                return(false);
            }
            LiveTvMediaItem liveTvMediaItem = playerContext.CurrentMediaItem as LiveTvMediaItem;
            ILivePlayer     player          = playerContext.CurrentPlayer as ILivePlayer;

            if (liveTvMediaItem == null || player == null)
            {
                return(false);
            }

            ITimeshiftContext context = liveTvMediaItem.TimeshiftContexes.LastOrDefault();

            if (context == null || context.Channel == null)
            {
                return(false);
            }

            ILocalization localization = ServiceRegistration.Get <ILocalization>();
            var           result       = await _tvHandler.ProgramInfo.GetNowNextProgramAsync(context.Channel);

            return(await InitActionsList(result.Success?result.Result[0] : null, context.Channel));
        }
        protected async override void Update()
        {
            // Don't update the current channel and program information if we are in zap osd.
            if (_tvHandler == null || (_zapTimer != null && _zapTimer.IsEventPending))
            {
                return;
            }

            // Update current programs for all channels of current group (visible inside MiniGuide).
            await UpdateAllCurrentPrograms();

            _zapChannelIndex = ChannelContext.Instance.Channels.CurrentIndex;

            if (_tvHandler.NumberOfActiveSlots < 1)
            {
                PiPAvailable = false;
                PiPEnabled   = false;
                return;
            }

            PiPAvailable = true;

            // get the current channel and program out of the LiveTvMediaItems' TimeshiftContexes
            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();
            IPlayerContext        playerContext        = playerContextManager.GetPlayerContext(PlayerChoice.PrimaryPlayer);

            if (playerContext != null)
            {
                ILivePlayer player = playerContext.CurrentPlayer as ILivePlayer;
                if (player != null)
                {
                    LiveTvMediaItem   item           = player.CurrentItem;
                    ITimeshiftContext context        = item == null ? null : item.TimeshiftContexes.LastOrDefault();
                    IProgram          currentProgram = null;
                    IProgram          nextProgram    = null;
                    IChannel          channel        = null;
                    if (context != null && context.Channel != null)
                    {
                        channel         = context.Channel;
                        ChannelName     = channel.Name;
                        ChannelLogoType = channel.GetFanArtMediaType();
                        if (_tvHandler.ProgramInfo != null)
                        {
                            var result = await _tvHandler.ProgramInfo.GetNowNextProgramAsync(channel);

                            if (result.Success)
                            {
                                currentProgram = result.Result[0];
                                nextProgram    = result.Result[1];
                                double progress = currentProgram == null ? 100d : (DateTime.Now - currentProgram.StartTime).TotalSeconds /
                                                  (currentProgram.EndTime - currentProgram.StartTime).TotalSeconds * 100;
                                _programProgressProperty.SetValue(progress);
                            }
                        }
                    }
                    CurrentProgram.SetProgram(currentProgram, channel);
                    NextProgram.SetProgram(nextProgram, channel);
                }
            }
        }
Exemple #9
0
        private void UpdateExistingMediaItem(MediaItem timeshiftMediaItem)
        {
            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();

            for (int index = 0; index < playerContextManager.NumActivePlayerContexts; index++)
            {
                IPlayerContext playerContext = playerContextManager.GetPlayerContext(index);
                if (playerContext == null)
                {
                    continue;
                }
                LiveTvMediaItem liveTvMediaItem    = playerContext.CurrentMediaItem as LiveTvMediaItem;
                LiveTvMediaItem newLiveTvMediaItem = timeshiftMediaItem as LiveTvMediaItem;
                // Check if this is "our" media item to update.
                if (liveTvMediaItem == null || newLiveTvMediaItem == null || !IsSameSlot(liveTvMediaItem, newLiveTvMediaItem))
                {
                    continue;
                }

                if (!IsSameLiveTvItem(liveTvMediaItem, newLiveTvMediaItem))
                {
                    // Switch MediaItem in current slot
                    playerContext.DoPlay(newLiveTvMediaItem);
                    // Clear former timeshift contexes (card change cause loss of buffer in rtsp mode).
                    liveTvMediaItem.TimeshiftContexes.Clear();
                }
                // Add new timeshift context
                AddTimeshiftContext(liveTvMediaItem, newLiveTvMediaItem.AdditionalProperties[LiveTvMediaItem.CHANNEL] as IChannel);
            }
        }
Exemple #10
0
        private bool InitActionsList()
        {
            _dialogActionsList.Clear();
            DialogHeader = "[SlimTvClient.RecordActions]";
            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();
            IPlayerContext        playerContext        = playerContextManager.GetPlayerContext(PlayerChoice.PrimaryPlayer);

            if (playerContext == null)
            {
                return(false);
            }
            LiveTvMediaItem liveTvMediaItem = playerContext.CurrentMediaItem as LiveTvMediaItem;
            LiveTvPlayer    player          = playerContext.CurrentPlayer as LiveTvPlayer;

            if (liveTvMediaItem == null || player == null)
            {
                return(false);
            }

            ITimeshiftContext context = player.TimeshiftContexes.LastOrDefault();

            if (context == null || context.Channel == null)
            {
                return(false);
            }

            IProgram      programNow;
            IProgram      programNext;
            ListItem      item;
            ILocalization localization = ServiceRegistration.Get <ILocalization>();
            bool          isRecording  = false;

            if (_tvHandler.ProgramInfo.GetNowNextProgram(context.Channel, out programNow, out programNext))
            {
                var recStatus = GetRecordingStatus(programNow);
                isRecording = recStatus.HasValue && recStatus.Value.HasFlag(RecordingStatus.Scheduled | RecordingStatus.Recording);
                item        = new ListItem(Consts.KEY_NAME, localization.ToString(isRecording ? "[SlimTvClient.StopCurrentRecording]" : "[SlimTvClient.RecordCurrentProgram]", programNow.Title))
                {
                    Command = new MethodDelegateCommand(() => CreateOrDeleteSchedule(programNow))
                };
                _dialogActionsList.Add(item);
            }
            if (!isRecording)
            {
                item = new ListItem(Consts.KEY_NAME, "[SlimTvClient.RecordManual]")
                {
                    Command = new MethodDelegateCommand(() => CreateOrDeleteSchedule(new Program
                    {
                        Title     = localization.ToString("[SlimTvClient.ManualRecordingTitle]"),
                        ChannelId = context.Channel.ChannelId,
                        StartTime = DateTime.Now,
                        EndTime   = DateTime.Now.AddDays(1)
                    }))
                };
                _dialogActionsList.Add(item);
            }
            _dialogActionsList.FireChange();
            return(true);
        }
        private async Task <bool> InitActionsList()
        {
            _dialogActionsList.Clear();
            DialogHeader = "[SlimTvClient.RecordActions]";
            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();
            IPlayerContext        playerContext        = playerContextManager.GetPlayerContext(PlayerChoice.PrimaryPlayer);

            if (playerContext == null)
            {
                return(false);
            }
            LiveTvMediaItem liveTvMediaItem = playerContext.CurrentMediaItem as LiveTvMediaItem;
            LiveTvPlayer    player          = playerContext.CurrentPlayer as LiveTvPlayer;

            if (liveTvMediaItem == null || player == null)
            {
                return(false);
            }

            ITimeshiftContext context = player.TimeshiftContexes.LastOrDefault();

            if (context == null || context.Channel == null)
            {
                return(false);
            }

            ListItem      item;
            ILocalization localization = ServiceRegistration.Get <ILocalization>();
            bool          isRecording  = false;
            var           result       = await _tvHandler.ProgramInfo.GetNowNextProgramAsync(context.Channel);

            if (result.Success)
            {
                IProgram programNow = result.Result[0];
                var      recStatus  = await GetRecordingStatusAsync(programNow);

                isRecording = recStatus.HasValue && recStatus.Value.HasFlag(RecordingStatus.Scheduled | RecordingStatus.Recording);
                item        = new ListItem(Consts.KEY_NAME, localization.ToString(isRecording ? "[SlimTvClient.StopCurrentRecording]" : "[SlimTvClient.RecordCurrentProgram]", programNow.Title))
                {
                    Command = new AsyncMethodDelegateCommand(() => CreateOrDeleteSchedule(programNow))
                };
                _dialogActionsList.Add(item);
            }
            if (!isRecording)
            {
                item = new ListItem(Consts.KEY_NAME, "[SlimTvClient.RecordManual]")
                {
                    Command = new AsyncMethodDelegateCommand(() => CreateOrDeleteScheduleByTimeAsync(context.Channel, DateTime.Now, DateTime.Now.AddDays(1)))
                };
                _dialogActionsList.Add(item);
            }
            _dialogActionsList.FireChange();
            return(true);
        }
        protected override void Update()
        {
            // Don't update the current channel and program information if we are in zap osd.
            if (_tvHandler == null || !_active || _zapTimer != null)
            {
                return;
            }

            if (_tvHandler.NumberOfActiveSlots < 1)
            {
                PiPAvailable = false;
                PiPEnabled   = false;
                return;
            }

            PiPAvailable = true;

            // get the current channel and program out of the LiveTvMediaItems' TimeshiftContexes
            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();
            IPlayerContext        playerContext        = playerContextManager.GetPlayerContext(PlayerChoice.PrimaryPlayer);

            if (playerContext != null)
            {
                LiveTvMediaItem liveTvMediaItem = playerContext.CurrentMediaItem as LiveTvMediaItem;
                LiveTvPlayer    player          = playerContext.CurrentPlayer as LiveTvPlayer;
                if (liveTvMediaItem != null && player != null)
                {
                    ITimeshiftContext context        = player.CurrentTimeshiftContext;
                    IProgram          currentProgram = null;
                    IProgram          nextProgram    = null;
                    if (context != null)
                    {
                        ChannelName    = context.Channel.Name;
                        currentProgram = context.Program;
                        if (currentProgram != null)
                        {
                            currentProgram = context.Program;
                            double progress = (DateTime.Now - currentProgram.StartTime).TotalSeconds /
                                              (currentProgram.EndTime - currentProgram.StartTime).TotalSeconds * 100;
                            _programProgressProperty.SetValue(progress);

                            IList <IProgram> nextPrograms;
                            DateTime         nextTime = currentProgram.EndTime.Add(TimeSpan.FromSeconds(10));
                            if (_tvHandler.ProgramInfo.GetPrograms(context.Channel, nextTime, nextTime, out nextPrograms))
                            {
                                nextProgram = nextPrograms[0];
                            }
                        }
                    }
                    CurrentProgram.SetProgram(currentProgram);
                    NextProgram.SetProgram(nextProgram);
                }
            }
        }
Exemple #13
0
        /// <summary>
        /// Creates a new <see cref="TimeshiftContext"/> and fills the <see cref="LiveTvMediaItem.TimeshiftContexes"/> with it.
        /// A new context is created for each channel change or for changed programs on same channel.
        /// </summary>
        /// <param name="timeshiftMediaItem">MediaItem</param>
        /// <param name="channel">Current channel.</param>
        private void AddOrUpdateTimeshiftContext(LiveTvMediaItem timeshiftMediaItem, IChannel channel)
        {
            TimeshiftContext tsContext = new TimeshiftContext {
                Channel = channel
            };

            // Remove the newly tuned channel from history if present
            timeshiftMediaItem.TimeshiftContexes.Where(tc => tc.Channel.ChannelId == channel.ChannelId).ToList().
            ForEach(context => timeshiftMediaItem.TimeshiftContexes.Remove(context));
            // Then add the new context to the end
            timeshiftMediaItem.TimeshiftContexes.Add(tsContext);
            timeshiftMediaItem.AdditionalProperties[LiveTvMediaItem.CHANNEL] = channel;
        }
Exemple #14
0
        private void AddTimeshiftContext(LiveTvMediaItem timeshiftMediaItem, IChannel channel)
        {
            IProgram         program   = GetCurrentProgram(channel);
            TimeshiftContext tsContext = new TimeshiftContext
            {
                Channel    = channel,
                Program    = program,
                TuneInTime = DateTime.Now
            };

            int tc = timeshiftMediaItem.TimeshiftContexes.Count;

            if (tc > 0)
            {
                ITimeshiftContext lastContext = timeshiftMediaItem.TimeshiftContexes[tc - 1];
                lastContext.TimeshiftDuration = DateTime.Now - lastContext.TuneInTime;
            }
            timeshiftMediaItem.TimeshiftContexes.Add(tsContext);
        }
Exemple #15
0
        protected virtual async Task <MediaItem> CreateMediaItem(int slotIndex, string streamUrl, IChannel channel, bool isTv, IChannel fullChannel)
        {
            LiveTvMediaItem tvStream = isTv
        ? SlimTvMediaItemBuilder.CreateMediaItem(slotIndex, streamUrl, fullChannel)
        : SlimTvMediaItemBuilder.CreateRadioMediaItem(slotIndex, streamUrl, fullChannel);

            if (tvStream != null)
            {
                // Add program infos to the LiveTvMediaItem
                var result = await GetNowNextProgramAsync(channel);

                if (result.Success)
                {
                    tvStream.AdditionalProperties[LiveTvMediaItem.CURRENT_PROGRAM] = result.Result[0];
                    tvStream.AdditionalProperties[LiveTvMediaItem.NEXT_PROGRAM]    = result.Result[1];
                }
                return(tvStream);
            }
            return(null);
        }
        protected virtual MediaItem CreateMediaItem(int slotIndex, string streamUrl, IChannel channel, bool isTv, IChannel fullChannel)
        {
            LiveTvMediaItem tvStream = isTv
        ? SlimTvMediaItemBuilder.CreateMediaItem(slotIndex, streamUrl, fullChannel)
        : SlimTvMediaItemBuilder.CreateRadioMediaItem(slotIndex, streamUrl, fullChannel);

            if (tvStream != null)
            {
                // Add program infos to the LiveTvMediaItem
                IProgram currentProgram;
                IProgram nextProgram;
                if (GetNowNextProgram(channel, out currentProgram, out nextProgram))
                {
                    tvStream.AdditionalProperties[LiveTvMediaItem.CURRENT_PROGRAM] = currentProgram;
                    tvStream.AdditionalProperties[LiveTvMediaItem.NEXT_PROGRAM]    = nextProgram;
                }
                return(tvStream);
            }
            return(null);
        }
Exemple #17
0
        private IPlayerContext existingPlayerContext(int slotIndex)
        {
            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();

            for (int index = 0; index < playerContextManager.NumActivePlayerContexts; index++)
            {
                IPlayerContext playerContext = playerContextManager.GetPlayerContext(index);
                if (playerContext == null)
                {
                    continue;
                }
                LiveTvMediaItem liveTvMediaItem = playerContext.CurrentMediaItem as LiveTvMediaItem;
                // Check if this is "our" media item to update.
                if (liveTvMediaItem == null || (int)liveTvMediaItem.AdditionalProperties[LiveTvMediaItem.SLOT_INDEX] != slotIndex)
                {
                    continue;
                }
                return(playerContext);
            }
            return(null);
        }
Exemple #18
0
        public Task <MetadataContainer> ParseChannelStreamAsync(int channelId, LiveTvMediaItem channelMediaItem)
        {
            var info    = new MetadataContainer();
            var edition = 0;

            info.AddEdition(edition);
            info.Metadata[edition].VideoContainerType = VideoContainer.Mp4;
            info.Video[edition] = new VideoStream
            {
                Codec       = VideoCodec.H264,
                AspectRatio = 1.777777777F,
                Width       = 1920,
                Height      = 1080,
                Framerate   = 25,
            };
            info.Audio[edition].Add(new AudioStream
            {
                Codec    = AudioCodec.Aac,
                Channels = 2
            });
            return(Task.FromResult(info));
        }
        protected override void EnumerateChapters(bool forceRefresh)
        {
            StreamInfoHandler chapterInfo;

            lock (SyncObj)
                chapterInfo = _chapterInfo;

            if (chapterInfo != null && !forceRefresh)
            {
                return;
            }

            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();

            for (int index = 0; index < playerContextManager.NumActivePlayerContexts; index++)
            {
                IPlayerContext playerContext = playerContextManager.GetPlayerContext(index);
                if (playerContext == null || playerContext.CurrentPlayer != this)
                {
                    continue;
                }

                LiveTvMediaItem liveTvMediaItem = playerContext.CurrentMediaItem as LiveTvMediaItem;
                if (liveTvMediaItem == null)
                {
                    continue;
                }

                _timeshiftContexes = liveTvMediaItem.TimeshiftContexes;
                chapterInfo        = new StreamInfoHandler();
                int i = 0;
                foreach (ITimeshiftContext timeshiftContext in _timeshiftContexes)
                {
                    chapterInfo.AddUnique(new StreamInfo(null, i++, GetContextTitle(timeshiftContext), 0));
                }
            }
            lock (SyncObj)
                _chapterInfo = chapterInfo;
        }
        private async Task <MetadataContainer> ParseSlimTvItemAsync(LiveTvMediaItem liveMedia)
        {
            try
            {
                LiveTvMediaItem liveMediaItem = new LiveTvMediaItem(liveMedia.MediaItemId, liveMedia.Aspects); //Preserve current aspects
                IChannel        channel       = (IChannel)liveMedia.AdditionalProperties[LiveTvMediaItem.CHANNEL];
                var             container     = await ParseChannelStreamAsync(channel.ChannelId, liveMediaItem).ConfigureAwait(false);

                if (container == null)
                {
                    return(null);
                }

                CopyAspects(liveMediaItem, liveMedia);
                return(container);
            }
            catch (Exception ex)
            {
                _logger.Error("MediaAnalyzer: Live mediaitem {0} could not be parsed", ex, liveMedia.MediaItemId);
            }
            return(null);
        }
Exemple #21
0
        public MediaItem CreateMediaItem(int slotIndex, string streamUrl, IChannel channel)
        {
            LiveTvMediaItem tvStream = SlimTvMediaItemBuilder.CreateMediaItem(slotIndex, streamUrl, channel);

            if (tvStream != null)
            {
                // Add program infos to the LiveTvMediaItem
                IProgram currentProgram;
                if (GetCurrentProgram(channel, out currentProgram))
                {
                    tvStream.AdditionalProperties[LiveTvMediaItem.CURRENT_PROGRAM] = currentProgram;
                }

                IProgram nextProgram;
                if (GetNextProgram(channel, out nextProgram))
                {
                    tvStream.AdditionalProperties[LiveTvMediaItem.NEXT_PROGRAM] = nextProgram;
                }

                return(tvStream);
            }
            return(null);
        }
Exemple #22
0
        private void UpdateExistingMediaItem(MediaItem timeshiftMediaItem, int slotIndex)
        {
            LiveTvMediaItem newLiveTvMediaItem = timeshiftMediaItem as LiveTvMediaItem;
            IPlayerContext  playerContext      = existingPlayerContext(slotIndex);

            if (playerContext == null)
            {
                return;
            }
            LiveTvMediaItem liveTvMediaItem = playerContext.CurrentMediaItem as LiveTvMediaItem;

            if (!IsSameLiveTvItem(liveTvMediaItem, newLiveTvMediaItem))
            {
                // Switch MediaItem in current slot, the LiveTvPlayer implements IReusablePlayer and will change its source without need to change full player.
                playerContext.DoPlay(newLiveTvMediaItem);
                // Copy old channel history into new item
                liveTvMediaItem.TimeshiftContexes.ToList().ForEach(tc => newLiveTvMediaItem.TimeshiftContexes.Add(tc));
                // Use new MediaItem, so new context will be added to new instance.
                liveTvMediaItem = newLiveTvMediaItem;
            }
            // Add new timeshift context
            AddOrUpdateTimeshiftContext(liveTvMediaItem, newLiveTvMediaItem.AdditionalProperties[LiveTvMediaItem.CHANNEL] as IChannel);
        }
        protected override void EnumerateChapters(bool forceRefresh)
        {
            IList <IChannel> channelHistory;

            lock (SyncObj)
                channelHistory = _channelHistory;

            if (channelHistory != null && !forceRefresh)
            {
                return;
            }

            IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>();

            for (int index = 0; index < playerContextManager.NumActivePlayerContexts; index++)
            {
                IPlayerContext playerContext = playerContextManager.GetPlayerContext(index);
                if (playerContext == null || playerContext.CurrentPlayer != this)
                {
                    continue;
                }

                LiveTvMediaItem liveTvMediaItem = playerContext.CurrentMediaItem as LiveTvMediaItem;
                if (liveTvMediaItem == null)
                {
                    continue;
                }

                _timeshiftContexes = liveTvMediaItem.TimeshiftContexes;
                var reversedList = new List <ITimeshiftContext>(_timeshiftContexes);
                reversedList.Reverse();
                channelHistory = reversedList.Select(timeshiftContext => timeshiftContext.Channel).ToList();
            }
            lock (SyncObj)
                _channelHistory = channelHistory;
        }
        protected override void EnumerateChapters(bool forceRefresh)
        {
            IList <IChannel> channelHistory;

            lock (SyncObj)
                channelHistory = _channelHistory;

            if (channelHistory != null && !forceRefresh)
            {
                return;
            }

            LiveTvMediaItem liveTvMediaItem = CurrentItem;

            if (liveTvMediaItem != null)
            {
                _timeshiftContexes = liveTvMediaItem.TimeshiftContexes;
                var reversedList = new List <ITimeshiftContext>(_timeshiftContexes);
                reversedList.Reverse();
                channelHistory = reversedList.Select(timeshiftContext => timeshiftContext.Channel).ToList();
            }
            lock (SyncObj)
                _channelHistory = channelHistory;
        }
        public static async Task <WebMediaInfo> ProcessAsync(IOwinContext context, string itemId, WebMediaType type)
        {
            if (itemId == null)
            {
                throw new BadRequestException("GetMediaInfo: itemId is null");
            }

            Guid                     mediaItemId;
            MediaItem                item;
            long                     duration  = 0;
            string                   container = string.Empty;
            MetadataContainer        info;
            List <WebVideoStream>    webVideoStreams    = new List <WebVideoStream>();
            List <WebAudioStream>    webAudioStreams    = new List <WebAudioStream>();
            List <WebSubtitleStream> webSubtitleStreams = new List <WebSubtitleStream>();

            if (type == WebMediaType.TV || type == WebMediaType.Radio)
            {
                int channelIdInt;
                if (int.TryParse(itemId, out channelIdInt))
                {
                    item = new LiveTvMediaItem(Guid.Empty);
                    info = MediaAnalyzer.ParseChannelStreamAsync(channelIdInt, (LiveTvMediaItem)item).Result;
                    if (info == null)
                    {
                        throw new BadRequestException(String.Format("GetMediaInfo: Channel {0} stream not available", itemId));
                    }
                }
                else
                {
                    throw new BadRequestException(String.Format("GetMediaInfo: Channel {0} not found", itemId));
                }
            }
            else if (Guid.TryParse(itemId, out mediaItemId) == true)
            {
                ISet <Guid> necessaryMIATypes = new HashSet <Guid>();
                necessaryMIATypes.Add(MediaAspect.ASPECT_ID);
                necessaryMIATypes.Add(ProviderResourceAspect.ASPECT_ID);
                necessaryMIATypes.Add(ImporterAspect.ASPECT_ID);

                ISet <Guid> optionalMIATypes = new HashSet <Guid>();
                optionalMIATypes.Add(VideoAspect.ASPECT_ID);
                optionalMIATypes.Add(VideoStreamAspect.ASPECT_ID);
                optionalMIATypes.Add(VideoAudioStreamAspect.ASPECT_ID);
                optionalMIATypes.Add(AudioAspect.ASPECT_ID);
                optionalMIATypes.Add(ImageAspect.ASPECT_ID);

                item = MediaLibraryAccess.GetMediaItemById(context, itemId, necessaryMIATypes, optionalMIATypes);

                if (item == null)
                {
                    throw new BadRequestException(String.Format("GetMediaInfo: No MediaItem found with id: {0}", itemId));
                }
            }
            else
            {
                throw new BadRequestException(String.Format("GetMediaInfo: Media not found with id: {0}", itemId));
            }

            // decide which type of media item we have
            info = await MediaAnalyzer.ParseMediaItemAsync(item);

            if (item.Aspects.ContainsKey(VideoAspect.ASPECT_ID))
            {
                var videoAspect       = item.GetAspect(VideoAspect.Metadata);
                var videoStreamAspect = item.GetAspect(VideoStreamAspect.Metadata);
                duration = Convert.ToInt64(videoStreamAspect.GetAttributeValue <long?>(VideoStreamAspect.ATTR_DURATION) ?? 0);
                bool interlaced = (videoStreamAspect.GetAttributeValue <string>(VideoStreamAspect.ATTR_VIDEO_TYPE) ?? "").ToLowerInvariant().Contains("interlaced");

                foreach (var data in info.Metadata)
                {
                    int edition       = data.Key;
                    int editionOffset = 0;
                    if (edition >= 0)
                    {
                        editionOffset = (edition + 1) * ProfileMediaItem.EDITION_OFFSET;
                    }

                    if (info.IsVideo(edition))
                    {
                        // Video
                        WebVideoStream webVideoStream = new WebVideoStream();
                        webVideoStream.Codec = Convert.ToString(info.Video[edition].Codec);
                        webVideoStream.DisplayAspectRatio       = Convert.ToDecimal(info.Video[edition].AspectRatio ?? 0);
                        webVideoStream.DisplayAspectRatioString = AspectRatioHelper.AspectRatioToString(Convert.ToDecimal(info.Video[edition].AspectRatio ?? 0));
                        webVideoStream.Height = Convert.ToInt32(info.Video[edition].Height ?? 0);
                        webVideoStream.Width  = Convert.ToInt32(info.Video[edition].Width ?? 0);
                        webVideoStreams.Add(webVideoStream);
                        webVideoStream.ID         = info.Video[edition].StreamIndex + editionOffset;
                        webVideoStream.Index      = 0;
                        webVideoStream.Interlaced = interlaced;

                        container = info.Metadata[edition].VideoContainerType.ToString();

                        // Audio
                        for (int i = 0; i < info.Audio[edition].Count; i++)
                        {
                            WebAudioStream webAudioStream = new WebAudioStream();
                            if (info.Audio[edition][i].Channels != null)
                            {
                                webAudioStream.Channels = info.Audio[edition][i].Channels.Value;
                            }

                            webAudioStream.Codec = info.Audio[edition][i].Codec.ToString();
                            webAudioStream.ID    = info.Audio[edition][i].StreamIndex + editionOffset;
                            webAudioStream.Index = i;
                            if (info.Audio[edition][i].Language != null)
                            {
                                string language = info.Audio[edition][i].Language == string.Empty ? UNDEFINED : info.Audio[edition][i].Language;
                                webAudioStream.Language = language;
                                if (language != UNDEFINED)
                                {
                                    webAudioStream.LanguageFull = new CultureInfo(language).EnglishName;
                                    if (item.HasEditions && item.Editions.Any(e => e.Value.SetNo == edition))
                                    {
                                        webAudioStream.Title = item.Editions.First(e => e.Key == edition).Value.Name;
                                    }
                                    else if (item.GetPlayData(out var mime, out var mediaName))
                                    {
                                        webAudioStream.Title = mediaName;
                                    }
                                    else
                                    {
                                        webAudioStream.Title = "?";
                                    }
                                    if (string.IsNullOrEmpty(webAudioStream.Codec) == false)
                                    {
                                        webAudioStream.Title += webAudioStream.Title?.Length > 0 ? $" ({webAudioStream.Codec.ToUpperInvariant()})" : webAudioStream.Codec.ToUpperInvariant();
                                    }
                                }
                            }
                            webAudioStreams.Add(webAudioStream);
                        }

                        // Subtitles
                        if (info.Subtitles[edition].Any())
                        {
                            int firstMediaIdx = info.Subtitles[edition].Keys.First();
                            for (int i = 0; i < info.Subtitles[edition][firstMediaIdx].Count; i++)
                            {
                                WebSubtitleStream webSubtitleStream = new WebSubtitleStream();
                                webSubtitleStream.Filename = info.Subtitles[edition][firstMediaIdx][i].IsEmbedded ? "Embedded" : info.Subtitles[edition][firstMediaIdx][i].SourcePath;
                                webSubtitleStream.ID       = info.Subtitles[edition][firstMediaIdx][i].StreamIndex + editionOffset;
                                webSubtitleStream.Index    = i;
                                if (info.Subtitles[edition][firstMediaIdx][i].Language != null)
                                {
                                    string language = info.Subtitles[edition][firstMediaIdx][i].Language == string.Empty ? UNDEFINED : info.Subtitles[edition][firstMediaIdx][i].Language;
                                    webSubtitleStream.Language     = language;
                                    webSubtitleStream.LanguageFull = language;
                                    if (language != UNDEFINED)
                                    {
                                        webSubtitleStream.LanguageFull = new CultureInfo(language).EnglishName;
                                    }
                                }
                                webSubtitleStreams.Add(webSubtitleStream);
                            }
                        }
                    }
                }
            }
            else if (item.Aspects.ContainsKey(AudioAspect.ASPECT_ID))
            {
                int edition = info.Metadata.Min(d => d.Key);
                if (info.IsAudio(edition))
                {
                    var audioAspect = item.GetAspect(AudioAspect.Metadata);
                    duration  = (long)audioAspect[AudioAspect.ATTR_DURATION];
                    container = info.Metadata[edition].AudioContainerType.ToString();
                }
            }
            else if (item.Aspects.ContainsKey(ImageAspect.ASPECT_ID))
            {
                int edition = info.Metadata.Min(d => d.Key);
                if (info.IsImage(edition))
                {
                    container = info.Metadata[edition].ImageContainerType.ToString();
                }
            }

            WebMediaInfo webMediaInfo = new WebMediaInfo
            {
                Duration        = duration * 1000,
                Container       = container,
                VideoStreams    = webVideoStreams,
                AudioStreams    = webAudioStreams,
                SubtitleStreams = webSubtitleStreams
            };

            return(webMediaInfo);
        }
Exemple #26
0
        public static async Task <WebBoolResult> ProcessAsync(IOwinContext context, string itemId, string clientDescription, string identifier, WebMediaType type, int?idleTimeout)
        {
            if (itemId == null)
            {
                throw new BadRequestException("InitStream: itemId is null");
            }
            if (clientDescription == null)
            {
                throw new BadRequestException("InitStream: clientDescription is null");
            }
            if (identifier == null)
            {
                throw new BadRequestException("InitStream: identifier is null");
            }

            StreamItem streamItem = new StreamItem
            {
                ItemType          = type,
                ClientDescription = clientDescription,
                IdleTimeout       = idleTimeout ?? -1,
                ClientIp          = context.Request.RemoteIpAddress
            };

            MediaItem mediaItem = new LiveTvMediaItem(Guid.Empty);

            if (streamItem.ItemType == WebMediaType.TV || streamItem.ItemType == WebMediaType.Radio)
            {
                int channelIdInt;
                if (!int.TryParse(itemId, out channelIdInt))
                {
                    throw new BadRequestException(string.Format("InitStream: Couldn't convert channelId to int: {0}", itemId));
                }

                streamItem.Title = "Live TV";
                if (streamItem.ItemType == WebMediaType.Radio)
                {
                    streamItem.Title = "Live Radio";
                }
                streamItem.LiveChannelId = channelIdInt;

                var info = await MediaAnalyzer.ParseChannelStreamAsync(channelIdInt, (LiveTvMediaItem)mediaItem);

                if (info == null)
                {
                    throw new BadRequestException(string.Format("InitStream: Couldn't parse channel stream: {0}", channelIdInt));
                }
            }
            else
            {
                Guid itemGuid;
                if (!Guid.TryParse(itemId, out itemGuid))
                {
                    throw new BadRequestException(string.Format("InitStream: Couldn't parse itemId: {0}", itemId));
                }

                ISet <Guid> necessaryMIATypes = new HashSet <Guid>();
                necessaryMIATypes.Add(MediaAspect.ASPECT_ID);
                necessaryMIATypes.Add(ProviderResourceAspect.ASPECT_ID);

                ISet <Guid> optionalMIATypes = new HashSet <Guid>();
                optionalMIATypes.Add(VideoAspect.ASPECT_ID);
                optionalMIATypes.Add(AudioAspect.ASPECT_ID);
                optionalMIATypes.Add(ImageAspect.ASPECT_ID);

                mediaItem = MediaLibraryAccess.GetMediaItemById(context, itemGuid, necessaryMIATypes, optionalMIATypes);
                if (mediaItem == null)
                {
                    throw new NotFoundException(string.Format("InitStream: Couldn't init stream! No MediaItem found with id: {0}", itemId));
                }
                streamItem.Title = mediaItem[MediaAspect.Metadata.AspectId][0].GetAttributeValue <string>(MediaAspect.ATTR_TITLE);
            }
            streamItem.RequestedMediaItem = mediaItem;

            // Add the stream to the stream controller
            bool result = await StreamControl.AddStreamItemAsync(identifier, streamItem);

            return(new WebBoolResult {
                Result = result
            });
        }
        public async Task <LiveTvMediaItem> InitializeChannel(int channelId)
        {
            IsLive         = true;
            MediaItemId    = Guid.Empty;
            MediaItemTitle = "Channel " + channelId;

            LiveTvMediaItem item = new LiveTvMediaItem(Guid.Empty);
            var             info = await MediaAnalyzer.ParseChannelStreamAsync(channelId, item);

            if (info == null)
            {
                Logger.Warn("MediaServer: Channel {0} couldn't be analyzed", channelId);
                return(null);
            }

            if (item.Aspects.ContainsKey(AudioAspect.ASPECT_ID))
            {
                IsAudio = true;
            }
            else if (item.Aspects.ContainsKey(VideoAspect.ASPECT_ID))
            {
                IsVideo = true;
            }
            else
            {
                Logger.Warn("MediaServer: Channel {0} contains no required aspect information", channelId);
                return(null);
            }

            if (MediaItemAspect.TryGetAttribute(item.Aspects, MediaAspect.ATTR_TITLE, out string title))
            {
                MediaItemTitle = title;
            }
            _edition = info.Metadata.Min(m => m.Key);

            string transcodeId = Guid.NewGuid().ToString() + "_" + Client.Profile.ID;

            if (MediaServerPlugin.Settings.TranscodingAllowed)
            {
                if (IsAudio)
                {
                    AudioTranscoding audio = TranscodeProfileManager.GetAudioTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Client.Profile.ID,
                                                                                         info, _edition, IsLive, transcodeId);
                    TranscodingParameter = audio;
                }
                else if (IsVideo)
                {
                    VideoTranscoding video = TranscodeProfileManager.GetVideoTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Client.Profile.ID,
                                                                                         info, _edition, Client.PreferredAudioLanguages, IsLive, transcodeId);
                    if (video != null)
                    {
                        if (video.TargetVideoContainer == VideoContainer.Hls)
                        {
                            IsSegmented = true;
                        }
                        if (MediaServerPlugin.Settings.HardcodedSubtitlesAllowed == false)
                        {
                            video.TargetSubtitleSupport = SubtitleSupport.None;
                        }
                    }
                    TranscodingParameter = video;
                }
            }

            if (TranscodingParameter == null)
            {
                if (IsVideo)
                {
                    TranscodingParameter = TranscodeProfileManager.GetLiveVideoTranscoding(info, Client.PreferredAudioLanguages, transcodeId);
                }
                else if (IsAudio)
                {
                    TranscodingParameter = TranscodeProfileManager.GetLiveAudioTranscoding(info, transcodeId);
                }
            }

            AssignDlnaMetadata(info, _edition);

            return(item);
        }
Exemple #28
0
 /// <summary>
 /// Checks if both <see cref="LiveTvMediaItem"/> are representing the same player slot.
 /// </summary>
 /// <param name="oldItem"></param>
 /// <param name="newItem"></param>
 /// <returns><c>true</c> if same</returns>
 protected bool IsSameSlot(LiveTvMediaItem oldItem, LiveTvMediaItem newItem)
 {
     return((int)oldItem.AdditionalProperties[LiveTvMediaItem.SLOT_INDEX] == (int)newItem.AdditionalProperties[LiveTvMediaItem.SLOT_INDEX]);
 }