protected void CheckResumeMenuInternal(MediaItem item)
        {
            IResumeState    resumeState = null;
            IUserManagement userProfileDataManagement = ServiceRegistration.Get <IUserManagement>();

            if (userProfileDataManagement.IsValidUser)
            {
                string resumeStateString;
                if (userProfileDataManagement.UserProfileDataManagement.GetUserMediaItemData(userProfileDataManagement.CurrentUser.ProfileId, item.MediaItemId, PlayerContext.KEY_RESUME_STATE, out resumeStateString))
                {
                    resumeState = ResumeStateBase.Deserialize(resumeStateString);
                }
            }

            if (resumeState == null)
            {
                // Asynchronously leave the current workflow state because we're called from a workflow model method
                IThreadPool threadPool = ServiceRegistration.Get <IThreadPool>();
                threadPool.Add(() =>
                {
                    LeaveCheckResumePlaybackSingleItemState();
                    PlayItem(item);
                });
                return;
            }
            _playMenuItems = new ItemsList();
            ListItem resumeItem = new ListItem
            {
                Command = new MethodDelegateCommand(() =>
                {
                    LeaveCheckResumePlaybackSingleItemState();
                    PlayItem(item, resumeState);
                })
            };
            PositionResumeState positionResume = resumeState as PositionResumeState;

            if (positionResume != null)
            {
                string playbackResume = LocalizationHelper.Translate(Consts.RES_PLAYBACK_RESUME_TIME, positionResume.ResumePosition.ToString(@"hh\:mm\:ss"));
                resumeItem.SetLabel(Consts.KEY_NAME, playbackResume);
            }
            else
            {
                resumeItem.SetLabel(Consts.KEY_NAME, Consts.RES_PLAYBACK_RESUME);
            }
            _playMenuItems.Add(resumeItem);
            ListItem playItem = new ListItem(Consts.KEY_NAME, Consts.RES_PLAYBACK_FROMSTART)
            {
                Command = new MethodDelegateCommand(() =>
                {
                    LeaveCheckResumePlaybackSingleItemState();
                    PlayItem(item);
                })
            };

            _playMenuItems.Add(playItem);
            IScreenManager screenManager = ServiceRegistration.Get <IScreenManager>();

            screenManager.ShowDialog(Consts.DIALOG_PLAY_MENU, (dialogName, dialogInstanceId) => LeaveCheckResumePlaybackSingleItemState());
        }
示例#2
0
        /// <summary>
        /// Gets a <see cref="IResumeState"/> from the player.
        /// </summary>
        /// <param name="state">Outputs resume state.</param>
        /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
        public virtual bool GetResumeState(out IResumeState state)
        {
            TimeSpan currentTime = CurrentTime;

            // Workaround for TsReader handling on playback end: it reports a negative position, so we treat it to "stream end"
            if (currentTime.TotalSeconds < 0)
            {
                currentTime = Duration;
            }
            TimeSpan duration = Duration;

            // If we already played back more then 99%, we don't want to ask user to resume playback.
            if (currentTime.TotalSeconds / duration.TotalSeconds > 0.99)
            {
                state = null;
            }
            else
            {
                state = new PositionResumeState
                {
                    ResumePosition             = CurrentTime,
                    ActiveResourceLocatorIndex = _mediaItem?.ActiveResourceLocatorIndex ?? 0,
                    ActiveEditionIndex         = _mediaItem?.ActiveEditionIndex ?? 0
                }
            };
            return(true);
        }
示例#3
0
        void OnMessageReceived(AsynchronousMessageQueue queue, SystemMessage message)
        {
            if (message.ChannelName == PlayerManagerMessaging.CHANNEL)
            {
                // React to player changes
                PlayerManagerMessaging.MessageType messageType = (PlayerManagerMessaging.MessageType)message.MessageType;
                IPlayerSlotController psc;
                // ServiceRegistration.Get<ILogger>().Debug("Trakt.tv: PlayerManagerMessage: {0}", message.MessageType);
                switch (messageType)
                {
                case PlayerManagerMessaging.MessageType.PlayerResumeState:
                    psc = (IPlayerSlotController)message.MessageData[PlayerManagerMessaging.PLAYER_SLOT_CONTROLLER];
                    IResumeState resumeState = (IResumeState)message.MessageData[PlayerManagerMessaging.KEY_RESUME_STATE];
                    Guid         mediaItemId = (Guid)message.MessageData[PlayerManagerMessaging.KEY_MEDIAITEM_ID];
                    HandleResumeInfo(psc, mediaItemId, resumeState);
                    break;

                case PlayerManagerMessaging.MessageType.PlayerError:
                case PlayerManagerMessaging.MessageType.PlayerEnded:
                case PlayerManagerMessaging.MessageType.PlayerStopped:
                    psc = (IPlayerSlotController)message.MessageData[PlayerManagerMessaging.PLAYER_SLOT_CONTROLLER];
                    HandleScrobble(psc, false);
                    break;

                case PlayerManagerMessaging.MessageType.PlayerStarted:
                    psc = (IPlayerSlotController)message.MessageData[PlayerManagerMessaging.PLAYER_SLOT_CONTROLLER];
                    HandleScrobble(psc, true);
                    break;
                }
            }
        }
示例#4
0
        void OnMessageReceived(AsynchronousMessageQueue queue, SystemMessage message)
        {
            if (message.ChannelName == PlayerManagerMessaging.CHANNEL)
            {
                // React to player changes
                PlayerManagerMessaging.MessageType messageType = (PlayerManagerMessaging.MessageType)message.MessageType;
                switch (messageType)
                {
                case PlayerManagerMessaging.MessageType.PlayerResumeState:
                    IResumeState        resumeState    = (IResumeState)message.MessageData[PlayerManagerMessaging.KEY_RESUME_STATE];
                    PositionResumeState positionResume = resumeState as PositionResumeState;
                    if (positionResume != null)
                    {
                        TimeSpan resumePosition = positionResume.ResumePosition;
                        _progress = Math.Min((int)(resumePosition.TotalSeconds * 100 / _duration.TotalSeconds), 100);
                    }
                    break;

                case PlayerManagerMessaging.MessageType.PlayerError:
                case PlayerManagerMessaging.MessageType.PlayerEnded:
                case PlayerManagerMessaging.MessageType.PlayerStopped:
                    StopScrobble();
                    break;

                case PlayerManagerMessaging.MessageType.PlayerStarted:
                    var psc = (IPlayerSlotController)message.MessageData[PlayerManagerMessaging.PLAYER_SLOT_CONTROLLER];
                    CreateScrobbleData(psc);
                    StartScrobble();
                    break;
                }
            }
        }
示例#5
0
        /// <summary>
        /// Sets a <see cref="IResumeState"/> to the player. The player is responsible to make the required initializations.
        /// </summary>
        /// <param name="state">Resume state.</param>
        /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
        public virtual bool SetResumeState(IResumeState state)
        {
            PositionResumeState pos = state as PositionResumeState;

            if (pos == null)
            {
                return(false);
            }

            if (_mediaItem != null)
            {
                // Check for multi-resource media items, first set the matching part, then the position
                if (pos.ActiveResourceLocatorIndex != _mediaItem.ActiveResourceLocatorIndex && pos.ActiveResourceLocatorIndex <= _mediaItem.MaximumResourceLocatorIndex ||
                    pos.ActiveEditionIndex != _mediaItem.ActiveEditionIndex && pos.ActiveEditionIndex <= _mediaItem.MaximumEditionIndex)
                {
                    _mediaItem.ActiveResourceLocatorIndex = pos.ActiveResourceLocatorIndex;
                    _mediaItem.ActiveEditionIndex         = pos.ActiveEditionIndex;
                    if (!NextItem(_mediaItem, StartTime.AtOnce))
                    {
                        return(false);
                    }
                }
            }
            CurrentTime = pos.ResumePosition;
            return(true);
        }
示例#6
0
        protected static bool TryGetPlayDuration(MediaItem mediaItem, IResumeState resumeState, out int playPercentage, out double playDuration)
        {
            playPercentage = 100;
            playDuration   = 0;
            PositionResumeState positionResume = resumeState as PositionResumeState;

            if (positionResume != null)
            {
                TimeSpan resumePosition = positionResume.ResumePosition;
                TimeSpan duration       = TimeSpan.FromSeconds(0);
                IList <MediaItemAspect> aspects;
                if (mediaItem.Aspects.TryGetValue(VideoStreamAspect.ASPECT_ID, out aspects))
                {
                    var  aspect  = aspects.First();
                    int? part    = (int?)aspect[VideoStreamAspect.ATTR_VIDEO_PART];
                    int? partSet = (int?)aspect[VideoStreamAspect.ATTR_VIDEO_PART_SET];
                    long?dur     = null;
                    if (!part.HasValue || part < 0)
                    {
                        dur = (long?)aspect[VideoStreamAspect.ATTR_DURATION];
                    }
                    else if (partSet.HasValue)
                    {
                        dur = aspects.Where(a => (int?)a[VideoStreamAspect.ATTR_VIDEO_PART_SET] == partSet &&
                                            aspect[VideoStreamAspect.ATTR_DURATION] != null).Sum(a => (long)a[VideoStreamAspect.ATTR_DURATION]);
                    }
                    if (dur.HasValue)
                    {
                        duration = TimeSpan.FromSeconds(dur.Value);
                    }
                }
                else if (mediaItem.Aspects.TryGetValue(AudioAspect.ASPECT_ID, out aspects))
                {
                    var  aspect = aspects.First();
                    long?dur    = aspect == null ? null : (long?)aspect[AudioAspect.ATTR_DURATION];
                    if (dur.HasValue)
                    {
                        duration = TimeSpan.FromSeconds(dur.Value);
                    }
                }

                if (duration.TotalSeconds > 0)
                {
                    playPercentage = (int)(resumePosition.TotalSeconds * 100 / duration.TotalSeconds);
                    playDuration   = resumePosition.TotalSeconds;
                }
                else
                {
                    playPercentage = 0;
                    playDuration   = 0;
                }
            }
            if (playPercentage > 100)
            {
                playPercentage = 100;
            }
            return(true);
        }
示例#7
0
 public static string Serialize(IResumeState resumeState)
 {
   if (resumeState == null)
     return null;
   DataContractSerializer serializer = new DataContractSerializer(typeof(ResumeStateBase));
   StringBuilder serialized = new StringBuilder();
   using (XmlWriter writer = XmlWriter.Create(serialized))
     serializer.WriteObject(writer, resumeState);
   return serialized.ToString();
 }
示例#8
0
        private void HandleResumeInfo(IPlayerSlotController psc, Guid mediaItemId, IResumeState resumeState)
        {
            PositionResumeState pos = resumeState as PositionResumeState;

            lock (_syncObj)
                if (_progressUpdateWorks.ContainsKey(psc))
                {
                    _progressUpdateWorks[psc].ResumePosition = pos != null ? pos.ResumePosition : _progressUpdateWorks[psc].Duration;
                }
        }
示例#9
0
        private void SaveResumePosition(SystemMessage message)
        {
            IResumeState        resumeState    = (IResumeState)message.MessageData[PlayerManagerMessaging.KEY_RESUME_STATE];
            PositionResumeState positionResume = resumeState as PositionResumeState;

            if (positionResume != null)
            {
                _resumePosition = positionResume.ResumePosition;
            }
        }
示例#10
0
        /// <summary>
        /// Sets a <see cref="IResumeState"/> to the player. The player is responsible to make the required initializations.
        /// </summary>
        /// <param name="state">Resume state.</param>
        /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
        public override bool SetResumeState(IResumeState state)
        {
            BinaryResumeState binaryResumeState = state as BinaryResumeState;

            if (binaryResumeState == null)
            {
                return(false);
            }
            SetResumeState(binaryResumeState.ResumeData);
            return(true);
        }
示例#11
0
        /// <summary>
        /// Sets a <see cref="IResumeState"/> to the player. The player is responsible to make the required initializations.
        /// </summary>
        /// <param name="state">Resume state.</param>
        /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
        public virtual bool SetResumeState(IResumeState state)
        {
            PositionResumeState pos = state as PositionResumeState;

            if (pos == null)
            {
                return(false);
            }
            CurrentTime = pos.ResumePosition;
            return(true);
        }
        public static string Serialize(IResumeState resumeState)
        {
            if (resumeState == null)
            {
                return(null);
            }
            DataContractSerializer serializer = new DataContractSerializer(typeof(ResumeStateBase));
            StringBuilder          serialized = new StringBuilder();

            using (XmlWriter writer = XmlWriter.Create(serialized))
                serializer.WriteObject(writer, resumeState);
            return(serialized.ToString());
        }
示例#13
0
 /// <summary>
 /// Gets a <see cref="IResumeState"/> from the player.
 /// </summary>
 /// <param name="state">Outputs resume state.</param>
 /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
 public override bool GetResumeState(out IResumeState state)
 {
     byte[] data;
     if (GetResumeState(out data))
     {
         state = new BinaryResumeState {
             ResumeData = data
         };
         return(true);
     }
     state = null;
     return(false);
 }
        protected void HandleResumeInfo(IPlayerSlotController psc, Guid mediaItemId, IResumeState resumeState)
        {
            // We can only handle resume info for valid MediaItemIds that are coming from MediaLibrary, not from local browsing.
            if (mediaItemId == Guid.Empty)
            {
                return;
            }

            string serialized = ResumeStateBase.Serialize(resumeState);

            IUserManagement userProfileDataManagement = ServiceRegistration.Get <IUserManagement>();

            if (userProfileDataManagement.IsValidUser)
            {
                userProfileDataManagement.UserProfileDataManagement.SetUserMediaItemData(userProfileDataManagement.CurrentUser.ProfileId, mediaItemId, PlayerContext.KEY_RESUME_STATE, serialized);
            }
        }
示例#15
0
        /// <summary>
        /// Gets a <see cref="IResumeState"/> from the player.
        /// </summary>
        /// <param name="state">Outputs resume state.</param>
        /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
        public virtual bool GetResumeState(out IResumeState state)
        {
            TimeSpan currentTime = CurrentTime;
            TimeSpan duration    = Duration;

            // If we already played back more then 99%, we don't want to ask user to resume playback.
            if (currentTime.TotalSeconds / duration.TotalSeconds > 0.99)
            {
                state = null;
            }
            else
            {
                state = new PositionResumeState {
                    ResumePosition = CurrentTime
                }
            };
            return(true);
        }
示例#16
0
        protected static void CompletePlayOrEnqueue(IPlayerContext pc, bool play, IResumeState resumeState = null)
        {
            IPlayerContextManager pcm      = ServiceRegistration.Get <IPlayerContextManager>();
            MediaModelSettings    settings = ServiceRegistration.Get <ISettingsManager>().Load <MediaModelSettings>();

            pc.CloseWhenFinished = settings.ClosePlayerWhenFinished; // Has to be done before starting the media item, else the slot will not close in case of an error / when the media item cannot be played
            if (play)
            {
                if (resumeState != null)
                {
                    pc.SetContextVariable(PlayerContext.KEY_RESUME_STATE, resumeState);
                }
                pc.Play();
                if (pc.AVType == AVType.Video)
                {
                    pcm.ShowFullscreenContent(true);
                }
            }
        }
示例#17
0
        /// <summary>
        /// Gets a <see cref="IResumeState"/> from the player.
        /// </summary>
        /// <param name="state">Outputs resume state.</param>
        /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
        public virtual bool GetResumeState(out IResumeState state)
        {
            TimeSpan currentTime = CurrentTime;
            TimeSpan duration    = Duration;

            // If we already played back more then 99%, we don't want to ask user to resume playback.
            if (currentTime.TotalSeconds / duration.TotalSeconds > 0.99)
            {
                state = null;
            }
            else
            {
                state = new PositionResumeState
                {
                    ResumePosition             = CurrentTime,
                    ActiveResourceLocatorIndex = _mediaItem?.ActiveResourceLocatorIndex ?? 0,
                    ActiveEditionIndex         = _mediaItem?.ActiveEditionIndex ?? 0
                }
            };
            return(true);
        }
示例#18
0
 /// <summary>
 /// Discards any current player and plays the specified media <paramref name="item"/>.
 /// </summary>
 /// <param name="item">Media item to be played.</param>
 /// <param name="resumeState">Contains optional information for players to resume playback.</param>
 public static async Task PlayItem(MediaItem item, IResumeState resumeState = null)
 {
     CloseSecondaryPlayerContext();
     await PlayOrEnqueueItem(item, true, PlayerContextConcurrencyMode.None, resumeState);
 }
示例#19
0
        /// <summary>
        /// Sends a message which contains information for resuming playback. The contained data can be specific for each player (can be position or some binary data).
        /// </summary>
        /// <param name="psc">Player slot controller of the player which is involved.</param>
        /// <param name="mediaItemId">ID of media item that was played.</param>
        /// <param name="resumeState">Resume state.</param>
        public static void SendPlayerResumeStateMessage(IPlayerSlotController psc, Guid mediaItemId, IResumeState resumeState)
        {
            SystemMessage msg = new SystemMessage(MessageType.PlayerResumeState);

            msg.MessageData[PLAYER_SLOT_CONTROLLER] = psc;
            msg.MessageData[KEY_MEDIAITEM_ID]       = mediaItemId;
            msg.MessageData[KEY_RESUME_STATE]       = resumeState;
            ServiceRegistration.Get <IMessageBroker>().Send(CHANNEL, msg);
        }
示例#20
0
 /// <summary>
 /// Gets a <see cref="IResumeState"/> from the player.
 /// </summary>
 /// <param name="state">Outputs resume state.</param>
 /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
 public override bool GetResumeState(out IResumeState state)
 {
   byte[] data;
   if (GetResumeState(out data))
   {
     state = new BinaryResumeState { ResumeData = data };
     return true;
   }
   state = null;
   return false;
 }
        void OnMessageReceived(AsynchronousMessageQueue queue, SystemMessage message)
        {
            if (message.ChannelName == WorkflowManagerMessaging.CHANNEL)
            {
                // Adjust our knowledge about the currently opened FSC/CP state if the user switches to one of them
                WorkflowManagerMessaging.MessageType messageType = (WorkflowManagerMessaging.MessageType)message.MessageType;
                switch (messageType)
                {
                case WorkflowManagerMessaging.MessageType.StatesPopped:
                    ICollection <Guid> statesRemoved = new List <Guid>(
                        ((IDictionary <Guid, NavigationContext>)message.MessageData[WorkflowManagerMessaging.CONTEXTS]).Keys);
                    HandleStatesRemovedFromWorkflowStack(statesRemoved);
                    break;

                case WorkflowManagerMessaging.MessageType.StatePushed:
                    NavigationContext context = (NavigationContext)message.MessageData[WorkflowManagerMessaging.CONTEXT];
                    Guid stateId = context.WorkflowState.StateId;
                    HandleWorkflowStatePushed(stateId);
                    break;
                }
            }
            else if (message.ChannelName == PlayerManagerMessaging.CHANNEL)
            {
                // React to player changes
                PlayerManagerMessaging.MessageType messageType = (PlayerManagerMessaging.MessageType)message.MessageType;
                IPlayerSlotController psc;
                switch (messageType)
                {
                case PlayerManagerMessaging.MessageType.PlayerResumeState:
                    psc = (IPlayerSlotController)message.MessageData[PlayerManagerMessaging.PLAYER_SLOT_CONTROLLER];
                    IResumeState resumeState = (IResumeState)message.MessageData[PlayerManagerMessaging.KEY_RESUME_STATE];
                    Guid         mediaItemId = (Guid)message.MessageData[PlayerManagerMessaging.KEY_MEDIAITEM_ID];
                    HandleResumeInfo(psc, mediaItemId, resumeState);
                    break;

                case PlayerManagerMessaging.MessageType.PlayerError:
                case PlayerManagerMessaging.MessageType.PlayerEnded:
                    psc = (IPlayerSlotController)message.MessageData[PlayerManagerMessaging.PLAYER_SLOT_CONTROLLER];
                    HandlePlayerEnded(psc);
                    break;

                case PlayerManagerMessaging.MessageType.PlayerStopped:
                    psc = (IPlayerSlotController)message.MessageData[PlayerManagerMessaging.PLAYER_SLOT_CONTROLLER];
                    HandlePlayerStopped(psc);
                    break;

                case PlayerManagerMessaging.MessageType.RequestNextItem:
                    psc = (IPlayerSlotController)message.MessageData[PlayerManagerMessaging.PLAYER_SLOT_CONTROLLER];
                    HandleRequestNextItem(psc);
                    break;
                }
                CleanupPlayerContexts();
                CheckMediaWorkflowStates_NoLock(); // Primary player could have been changed or closed or CP player could have been closed
            }
            else if (message.ChannelName == PlayerContextManagerMessaging.CHANNEL)
            {
                // React to internal player context manager changes
                PlayerContextManagerMessaging.MessageType messageType = (PlayerContextManagerMessaging.MessageType)message.MessageType;
                switch (messageType)
                {
                case PlayerContextManagerMessaging.MessageType.UpdatePlayerRolesInternal:
                    PlayerContext newCurrentPlayer = (PlayerContext)message.MessageData[PlayerContextManagerMessaging.NEW_CURRENT_PLAYER_CONTEXT];
                    PlayerContext newAudioPlayer   = (PlayerContext)message.MessageData[PlayerContextManagerMessaging.NEW_AUDIO_PLAYER_CONTEXT];
                    HandleUpdatePlayerRoles(newCurrentPlayer, newAudioPlayer);
                    break;
                    // PlayerContextManagerMessaging.MessageType.CurrentPlayerChanged not handled here
                }
            }
        }
示例#22
0
 /// <summary>
 /// Discards any current player and plays the specified media <paramref name="item"/>.
 /// </summary>
 /// <param name="item">Media item to be played.</param>
 /// <param name="resumeState">Contains optional information for players to resume playback.</param>
 public static void PlayItem(MediaItem item, IResumeState resumeState = null)
 {
   CloseSecondaryPlayerContext();
   PlayOrEnqueueItem(item, true, PlayerContextConcurrencyMode.None, resumeState);
 }
示例#23
0
        public void Init(MediaItem mediaItem)
        {
            if (mediaItem == null)
            {
                SetEmpty();
                return;
            }

            int currentPlayCount;

            MediaItemAspect.TryGetAttribute(mediaItem.Aspects, MediaAspect.ATTR_PLAYCOUNT, 0, out currentPlayCount);

            if (mediaItem.UserData.ContainsKey(UserDataKeysKnown.KEY_PLAY_PERCENTAGE))
            {
                PlayPercentage = Convert.ToInt32(mediaItem.UserData[UserDataKeysKnown.KEY_PLAY_PERCENTAGE]);
            }
            else if (mediaItem.UserData.ContainsKey(PlayerContext.KEY_RESUME_STATE))
            {
                IResumeState        resumeState    = ResumeStateBase.Deserialize(mediaItem.UserData[PlayerContext.KEY_RESUME_STATE]);
                PositionResumeState positionResume = resumeState as PositionResumeState;
                if (positionResume != null)
                {
                    TimeSpan resumePosition = positionResume.ResumePosition;
                    TimeSpan duration       = TimeSpan.FromSeconds(0);
                    IList <MediaItemAspect> aspects;
                    if (mediaItem.Aspects.TryGetValue(VideoStreamAspect.ASPECT_ID, out aspects))
                    {
                        var  aspect  = aspects.First();
                        int? part    = (int?)aspect[VideoStreamAspect.ATTR_VIDEO_PART];
                        int? partSet = (int?)aspect[VideoStreamAspect.ATTR_VIDEO_PART_SET];
                        long?dur     = null;
                        if (!part.HasValue || part < 0)
                        {
                            dur = (long?)aspect[VideoStreamAspect.ATTR_DURATION];
                        }
                        else if (partSet.HasValue)
                        {
                            dur = aspects.Where(a => (int?)a[VideoStreamAspect.ATTR_VIDEO_PART_SET] == partSet &&
                                                aspect[VideoStreamAspect.ATTR_DURATION] != null).Sum(a => (long)a[VideoStreamAspect.ATTR_DURATION]);
                        }
                        if (dur.HasValue)
                        {
                            duration = TimeSpan.FromSeconds(dur.Value);
                        }
                    }
                    else if (mediaItem.Aspects.TryGetValue(AudioAspect.ASPECT_ID, out aspects))
                    {
                        var  aspect = aspects.First();
                        long?dur    = aspect == null ? null : (long?)aspect[AudioAspect.ATTR_DURATION];
                        if (dur.HasValue)
                        {
                            duration = TimeSpan.FromSeconds(dur.Value);
                        }
                    }
                    if (duration.TotalSeconds > 0)
                    {
                        PlayPercentage = (int)(resumePosition.TotalSeconds * 100 / duration.TotalSeconds);
                    }
                    else if (currentPlayCount > 0)
                    {
                        PlayPercentage = 100;
                    }
                    else
                    {
                        PlayPercentage = 0;
                    }
                }
            }
            else
            {
                PlayPercentage = 0;
            }
            if (mediaItem.UserData.ContainsKey(UserDataKeysKnown.KEY_PLAY_COUNT))
            {
                PlayCount = Convert.ToInt32(mediaItem.UserData[UserDataKeysKnown.KEY_PLAY_COUNT]);
            }
            else
            {
                PlayCount = currentPlayCount;
            }
        }
 /// <summary>
 /// Sends a message which contains information for resuming playback. The contained data can be specific for each player (can be position or some binary data).
 /// </summary>
 /// <param name="psc">Player slot controller of the player which is involved.</param>
 /// <param name="mediaItemId">ID of media item that was played.</param>
 /// <param name="resumeState">Resume state.</param>
 public static void SendPlayerResumeStateMessage(IPlayerSlotController psc, Guid mediaItemId, IResumeState resumeState)
 {
   SystemMessage msg = new SystemMessage(MessageType.PlayerResumeState);
   msg.MessageData[PLAYER_SLOT_CONTROLLER] = psc;
   msg.MessageData[KEY_MEDIAITEM_ID] = mediaItemId;
   msg.MessageData[KEY_RESUME_STATE] = resumeState;
   ServiceRegistration.Get<IMessageBroker>().Send(CHANNEL, msg);
 }
示例#25
0
 private void HandleResumeInfo(IPlayerSlotController psc, Guid mediaItemId, IResumeState resumeState)
 {
   PositionResumeState pos = resumeState as PositionResumeState;
   lock (_syncObj)
     if (_progressUpdateWorks.ContainsKey(psc))
       _progressUpdateWorks[psc].ResumePosition = pos != null ? pos.ResumePosition : _progressUpdateWorks[psc].Duration;
 }
示例#26
0
    /// <summary>
    /// Depending on parameter <paramref name="play"/>, plays or enqueues the specified media <paramref name="item"/>.
    /// </summary>
    /// <param name="item">Media item to be played.</param>
    /// <param name="play">If <c>true</c>, plays the specified <paramref name="item"/>, else enqueues it.</param>
    /// <param name="concurrencyMode">Determines if the media item will be played or enqueued in concurrency mode.</param>
    /// <param name="resumeState">Contains optional information for players to resume playback.</param>
    public static void PlayOrEnqueueItem(MediaItem item, bool play, PlayerContextConcurrencyMode concurrencyMode, IResumeState resumeState = null)
    {
      IPlayerContextManager pcm = ServiceRegistration.Get<IPlayerContextManager>();
      AVType avType = pcm.GetTypeOfMediaItem(item);
      IPlayerContext pc = PreparePlayerContext(avType, play, concurrencyMode);
      if (pc == null)
        return;

      // Always add items to playlist. This allows audio playlists as well as video/image playlists.
      pc.Playlist.Add(item);

      ServiceRegistration.Get<IThreadPool>().Add(() => CompletePlayOrEnqueue(pc, play, resumeState));
    }
示例#27
0
 protected static void CompletePlayOrEnqueue(IPlayerContext pc, bool play, IResumeState resumeState = null)
 {
   IPlayerContextManager pcm = ServiceRegistration.Get<IPlayerContextManager>();
   MediaModelSettings settings = ServiceRegistration.Get<ISettingsManager>().Load<MediaModelSettings>();
   pc.CloseWhenFinished = settings.ClosePlayerWhenFinished; // Has to be done before starting the media item, else the slot will not close in case of an error / when the media item cannot be played
   if (play)
   {
     if (resumeState != null)
       pc.SetContextVariable(PlayerContext.KEY_RESUME_STATE, resumeState);
     pc.Play();
     if (pc.AVType == AVType.Video)
       pcm.ShowFullscreenContent(true);
   }
 }
示例#28
0
 /// <summary>
 /// Gets a <see cref="IResumeState"/> from the player.
 /// </summary>
 /// <param name="state">Outputs resume state.</param>
 /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
 public virtual bool GetResumeState(out IResumeState state)
 {
   TimeSpan currentTime = CurrentTime;
   TimeSpan duration = Duration;
   // If we already played back more then 99%, we don't want to ask user to resume playback.
   if (currentTime.TotalSeconds / duration.TotalSeconds > 0.99)
     state = null;
   else
     state = new PositionResumeState { ResumePosition = CurrentTime };
   return true;
 }
示例#29
0
        /// <summary>
        /// Depending on parameter <paramref name="play"/>, plays or enqueues the specified media <paramref name="item"/>.
        /// </summary>
        /// <param name="item">Media item to be played.</param>
        /// <param name="play">If <c>true</c>, plays the specified <paramref name="item"/>, else enqueues it.</param>
        /// <param name="concurrencyMode">Determines if the media item will be played or enqueued in concurrency mode.</param>
        /// <param name="resumeState">Contains optional information for players to resume playback.</param>
        public static async Task PlayOrEnqueueItem(MediaItem item, bool play, PlayerContextConcurrencyMode concurrencyMode, IResumeState resumeState = null)
        {
            IPlayerContextManager pcm = ServiceRegistration.Get <IPlayerContextManager>();
            AVType         avType     = pcm.GetTypeOfMediaItem(item);
            IPlayerContext pc         = PreparePlayerContext(avType, play, concurrencyMode);

            if (pc == null)
            {
                return;
            }

            // Always add items to playlist. This allows audio playlists as well as video/image playlists.
            pc.Playlist.Add(item);

            await CompletePlayOrEnqueue(pc, play, resumeState);
        }
        public bool Play(MediaItem mediaItem, StartTime startTime)
        {
            IPlayer player = null;

            try
            {
                IReusablePlayer rp;
                lock (SyncObj)
                {
                    CheckActive();
                    player = _player;
                    rp     = _player as IReusablePlayer;
                }
                if (rp != null)
                {
                    if (rp.NextItem(mediaItem, startTime))
                    {
                        OnPlayerStarted(rp);
                        return(true);
                    }
                }
                ReleasePlayer_NoLock();
                ICollection <Exception> exceptions;
                player = _playerManager.BuildPlayer_NoLock(mediaItem, out exceptions);
                if (player == null)
                {
                    HandleUnableToPlay(mediaItem, exceptions);
                    OnPlaybackError(null);
                }
                else
                {
                    IMediaPlaybackControl mpc;
                    IDisposable           disposePlayer = null;
                    lock (SyncObj)
                    {
                        if (_player != null)
                        {
                            disposePlayer = _player as IDisposable; // If we got a race condition between the locks
                        }
                        _player = player;
                        mpc     = player as IMediaPlaybackControl;
                    }
                    RegisterPlayerEvents_NoLock(player);
                    CheckAudio_NoLock();
                    if (disposePlayer != null)
                    {
                        disposePlayer.Dispose();
                    }
                    OnPlayerStarted(player);

                    // Handling of resume info.
                    object resumeObject;
                    if (ContextVariables.TryGetValue(PlayerContext.KEY_RESUME_STATE, out resumeObject))
                    {
                        IResumeState     resumeState     = (IResumeState)resumeObject;
                        IResumablePlayer resumablePlayer = player as IResumablePlayer;
                        if (resumablePlayer != null)
                        {
                            resumablePlayer.SetResumeState(resumeState);
                        }
                    }

                    if (mpc != null)
                    {
                        mpc.Resume();
                    }
                    return(true);
                }
                return(false);
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Warn("PlayerSlotController: Error playing '{0}'", e, mediaItem);
                IDisposable disposePlayer = player as IDisposable;
                if (disposePlayer != null)
                {
                    disposePlayer.Dispose();
                }
                return(false);
            }
        }
示例#31
0
        protected async Task CheckResumeMenuInternal(MediaItem item, int edition)
        {
            // First make sure the correct edition is selected
            if (edition <= item.MaximumEditionIndex)
            {
                item.ActiveEditionIndex = edition;
            }

            IResumeState    resumeState = null;
            IUserManagement userProfileDataManagement = ServiceRegistration.Get <IUserManagement>();

            if (userProfileDataManagement.IsValidUser)
            {
                var userResult = await userProfileDataManagement.UserProfileDataManagement.GetUserMediaItemDataAsync(userProfileDataManagement.CurrentUser.ProfileId, item.MediaItemId, PlayerContext.KEY_RESUME_STATE);

                if (userResult.Success)
                {
                    resumeState = ResumeStateBase.Deserialize(userResult.Result);
                }
            }

            // Check if resume state matches the current edition, if not start from beginning
            IResumeStateEdition rse = resumeState as IResumeStateEdition;

            if (rse != null && rse.ActiveEditionIndex != edition)
            {
                resumeState = null;
            }

            if (resumeState == null)
            {
                // Asynchronously leave the current workflow state because we're called from a workflow model method
                //await Task.Yield();
                await Task.Run(async() =>
                {
                    LeaveCheckResumePlaybackSingleItemState();
                    await PlayItem(item);
                });

                return;
            }
            _playMenuItems = new ItemsList();
            ListItem resumeItem = new ListItem
            {
                Command = new AsyncMethodDelegateCommand(() =>
                {
                    LeaveCheckResumePlaybackSingleItemState();
                    return(PlayItem(item, resumeState));
                })
            };
            PositionResumeState positionResume = resumeState as PositionResumeState;

            if (positionResume != null)
            {
                string playbackResume = LocalizationHelper.Translate(Consts.RES_PLAYBACK_RESUME_TIME, positionResume.ResumePosition.ToString(@"hh\:mm\:ss"));
                resumeItem.SetLabel(Consts.KEY_NAME, playbackResume);
            }
            else
            {
                resumeItem.SetLabel(Consts.KEY_NAME, Consts.RES_PLAYBACK_RESUME);
            }
            _playMenuItems.Add(resumeItem);
            ListItem playItem = new ListItem(Consts.KEY_NAME, Consts.RES_PLAYBACK_FROMSTART)
            {
                Command = new AsyncMethodDelegateCommand(() =>
                {
                    LeaveCheckResumePlaybackSingleItemState();
                    return(PlayItem(item));
                })
            };

            _playMenuItems.Add(playItem);
            IScreenManager screenManager = ServiceRegistration.Get <IScreenManager>();

            screenManager.ShowDialog(Consts.DIALOG_PLAY_MENU, (dialogName, dialogInstanceId) => LeaveCheckResumePlaybackSingleItemState());
        }
示例#32
0
 /// <summary>
 /// Sets a <see cref="IResumeState"/> to the player. The player is responsible to make the required initializations.
 /// </summary>
 /// <param name="state">Resume state.</param>
 /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
 public override bool SetResumeState(IResumeState state)
 {
   BinaryResumeState binaryResumeState = state as BinaryResumeState;
   if (binaryResumeState == null)
     return false;
   SetResumeState(binaryResumeState.ResumeData);
   return true;
 }
示例#33
0
 /// <summary>
 /// Sets a <see cref="IResumeState"/> to the player. The player is responsible to make the required initializations.
 /// </summary>
 /// <param name="state">Resume state.</param>
 /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns>
 public virtual bool SetResumeState(IResumeState state)
 {
   PositionResumeState pos = state as PositionResumeState;
   if (pos == null)
     return false;
   CurrentTime = pos.ResumePosition;
   return true;
 }
示例#34
0
        protected async Task HandleResumeInfo(IPlayerSlotController psc, MediaItem mediaItem, IResumeState resumeState)
        {
            // We can only handle resume info for valid MediaItemIds that are coming from MediaLibrary
            if (mediaItem == null)
            {
                return;
            }
            // Not from local browsing
            if (mediaItem.MediaItemId == Guid.Empty)
            {
                return;
            }
            // And not from stubs
            if (mediaItem.IsStub)
            {
                return;
            }

            string serialized = ResumeStateBase.Serialize(resumeState);

            IUserManagement userProfileDataManagement = ServiceRegistration.Get <IUserManagement>();

            if (userProfileDataManagement.IsValidUser)
            {
                await userProfileDataManagement.UserProfileDataManagement.SetUserMediaItemDataAsync(userProfileDataManagement.CurrentUser.ProfileId, mediaItem.MediaItemId, PlayerContext.KEY_RESUME_STATE, serialized);
            }

            if (!mediaItem.UserData.ContainsKey(PlayerContext.KEY_RESUME_STATE))
            {
                mediaItem.UserData.Add(PlayerContext.KEY_RESUME_STATE, "");
            }
            mediaItem.UserData[PlayerContext.KEY_RESUME_STATE] = serialized;

            int    playPercentage = 0;
            double playDuration   = 0;

            if (TryGetPlayDuration(mediaItem, resumeState, out playPercentage, out playDuration))
            {
                await NotifyPlayback(mediaItem, playPercentage, playDuration);
            }
        }
        public virtual void Update(MediaItem mediaItem)
        {
            if (!_mediaItem.Equals(mediaItem))
            {
                throw new ArgumentException("Update can only be done for the same MediaItem!", "mediaItem");
            }

            int?currentPlayCount = null;
            SingleMediaItemAspect mediaAspect;

            if (MediaItemAspect.TryGetAspect(mediaItem.Aspects, MediaAspect.Metadata, out mediaAspect))
            {
                Title            = (string)mediaAspect[MediaAspect.ATTR_TITLE];
                SortString       = (string)mediaAspect[MediaAspect.ATTR_SORT_TITLE];
                Rating           = (int?)mediaAspect[MediaAspect.ATTR_RATING] ?? 0;
                currentPlayCount = (int?)mediaAspect[MediaAspect.ATTR_PLAYCOUNT] ?? 0;
                Virtual          = (bool?)mediaAspect[MediaAspect.ATTR_ISVIRTUAL];
            }

            TimeSpan?duration = null;
            IList <MediaItemAspect> aspects;

            if (mediaItem.Aspects.TryGetValue(VideoStreamAspect.ASPECT_ID, out aspects))
            {
                var  aspect  = aspects.First();
                int? part    = (int?)aspect[VideoStreamAspect.ATTR_VIDEO_PART];
                int? partSet = (int?)aspect[VideoStreamAspect.ATTR_VIDEO_PART_SET];
                long?dur     = null;
                if (!part.HasValue || part < 0)
                {
                    dur = (long?)aspect[VideoStreamAspect.ATTR_DURATION];
                }
                else if (partSet.HasValue)
                {
                    dur = aspects.Where(a => (int?)a[VideoStreamAspect.ATTR_VIDEO_PART_SET] == partSet &&
                                        aspect[VideoStreamAspect.ATTR_DURATION] != null).Sum(a => (long)a[VideoStreamAspect.ATTR_DURATION]);
                }
                if (dur.HasValue)
                {
                    duration = TimeSpan.FromSeconds(dur.Value);
                }
            }
            else if (mediaItem.Aspects.TryGetValue(AudioAspect.ASPECT_ID, out aspects))
            {
                var  aspect = aspects.First();
                long?dur    = aspect == null ? null : (long?)aspect[AudioAspect.ATTR_DURATION];
                if (dur.HasValue)
                {
                    duration = TimeSpan.FromSeconds(dur.Value);
                }
            }
            else if (mediaItem.Aspects.TryGetValue(MovieAspect.ASPECT_ID, out aspects))
            {
                var aspect = aspects.First();
                int?dur    = aspect == null ? null : (int?)aspect[MovieAspect.ATTR_RUNTIME_M];
                if (dur.HasValue)
                {
                    duration = TimeSpan.FromMinutes(dur.Value);
                }
            }
            Duration = duration.HasValue ? FormattingUtils.FormatMediaDuration(duration.Value) : string.Empty;

            if (mediaItem.UserData.ContainsKey(UserDataKeysKnown.KEY_PLAY_PERCENTAGE))
            {
                WatchPercentage = mediaItem.UserData[UserDataKeysKnown.KEY_PLAY_PERCENTAGE];
            }
            else if (mediaItem.UserData.ContainsKey(PlayerContext.KEY_RESUME_STATE))
            {
                IResumeState        resumeState    = ResumeStateBase.Deserialize(mediaItem.UserData[PlayerContext.KEY_RESUME_STATE]);
                PositionResumeState positionResume = resumeState as PositionResumeState;
                if (positionResume != null && duration.HasValue)
                {
                    TimeSpan resumePosition = positionResume.ResumePosition;
                    if (duration.Value.TotalSeconds > 0)
                    {
                        WatchPercentage = ((int)(resumePosition.TotalSeconds * 100 / duration.Value.TotalSeconds)).ToString();
                    }
                    else if (currentPlayCount > 0)
                    {
                        WatchPercentage = "100";
                    }
                    else
                    {
                        WatchPercentage = "0";
                    }
                }
            }

            if (mediaItem.UserData.ContainsKey(UserDataKeysKnown.KEY_PLAY_COUNT))
            {
                PlayCount = Convert.ToInt32(mediaItem.UserData[UserDataKeysKnown.KEY_PLAY_COUNT]);
            }
            else if (currentPlayCount.HasValue)
            {
                PlayCount = currentPlayCount.Value;
            }

            FireChange();
        }
示例#36
0
        protected void HandleResumeInfo(IPlayerSlotController psc, MediaItem mediaItem, IResumeState resumeState)
        {
            // We can only handle resume info for valid MediaItemIds that are coming from MediaLibrary, not from local browsing.
            if (mediaItem == null)
            {
                return;
            }
            if (mediaItem.MediaItemId == Guid.Empty)
            {
                return;
            }

            string serialized = ResumeStateBase.Serialize(resumeState);

            IUserManagement userProfileDataManagement = ServiceRegistration.Get <IUserManagement>();

            if (userProfileDataManagement.IsValidUser)
            {
                userProfileDataManagement.UserProfileDataManagement.SetUserMediaItemData(userProfileDataManagement.CurrentUser.ProfileId, mediaItem.MediaItemId, PlayerContext.KEY_RESUME_STATE, serialized);
            }

            if (!mediaItem.UserData.ContainsKey(PlayerContext.KEY_RESUME_STATE))
            {
                mediaItem.UserData.Add(PlayerContext.KEY_RESUME_STATE, "");
            }
            mediaItem.UserData[PlayerContext.KEY_RESUME_STATE] = serialized;

            int playPercentage = GetPlayPercentage(mediaItem, resumeState);

            NotifyPlayback(mediaItem, playPercentage);
        }