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()); }
/// <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); }
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; } } }
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; } } }
/// <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 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); }
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(); }
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 override bool SetResumeState(IResumeState state) { BinaryResumeState binaryResumeState = state as BinaryResumeState; if (binaryResumeState == null) { return(false); } SetResumeState(binaryResumeState.ResumeData); 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); } 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()); }
/// <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); } }
/// <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); }
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); } } }
/// <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); }
/// <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); }
/// <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); }
/// <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 } } }
/// <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); }
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); }
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; }
/// <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)); }
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); } }
/// <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> /// 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); } }
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()); }
/// <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; }
/// <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; }
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(); }
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); }