/// <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); }
/// <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); }
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()); }
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; } } }
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); }
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; } }
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; } }
/// <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); }
/// <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); }
/// <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); }
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()); }
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; } }
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(); }