private void CreateScrobbleData(IPlayerSlotController psc) { IPlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null || pc.CurrentMediaItem == null) { return; } IMediaPlaybackControl pmc = pc.CurrentPlayer as IMediaPlaybackControl; if (pmc == null) { return; } _duration = pmc.Duration; if (IsMovie(pc.CurrentMediaItem)) { Guid movieMediaItemId = pc.CurrentMediaItem.MediaItemId; currentPlayingMediaItem = GetMediaItem(movieMediaItemId, new Guid[] { MediaAspect.ASPECT_ID, ExternalIdentifierAspect.ASPECT_ID, MovieAspect.ASPECT_ID }); _dataMovie = CreateMovieData(currentPlayingMediaItem); } if (IsSeries(pc.CurrentMediaItem)) { Guid seriesMediaItemId = pc.CurrentMediaItem.MediaItemId; currentPlayingMediaItem = GetMediaItem(seriesMediaItemId, new Guid[] { MediaAspect.ASPECT_ID, ExternalIdentifierAspect.ASPECT_ID, EpisodeAspect.ASPECT_ID }); _dataEpisode = CreateEpisodeData(currentPlayingMediaItem); } }
protected static string GetTargetBackgroundScreen() { IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>(); if (playerContextManager.NumActivePlayerContexts == 0) { return(Consts.SCREEN_DEFAULT_BACKGROUND); } IPlayerContext pcPrimary = playerContextManager.PrimaryPlayerContext; IPlayerSlotController pscPrimary = pcPrimary != null && pcPrimary.IsActive ? pcPrimary.PlayerSlotController : null; IPlayer pPrimary = pscPrimary == null ? null : pscPrimary.CurrentPlayer; if (pPrimary != null) { if (pPrimary is IVideoPlayer) { return(Consts.SCREEN_VIDEO_BACKGROUND); } if (pPrimary is IImagePlayer) { return(Consts.SCREEN_IMAGE_BACKGROUND); } } return(Consts.SCREEN_DEFAULT_BACKGROUND); }
public void CloseSlot(IPlayerSlotController playerSlotController) { PlayerSlotController psc = playerSlotController as PlayerSlotController; if (psc == null) { return; } bool isAudio = psc.IsAudioSlot && !psc.IsClosed; PlayerSlotController nextPsc; lock (_syncObj) { int nextIndex = _slots.IndexOf(psc); _slots.Remove(psc); int numSlots = _slots.Count; nextIndex = numSlots == 0 ? 0 : (nextIndex + 1) % numSlots; nextPsc = numSlots > nextIndex ? _slots[nextIndex] : null; } psc.Close_NoLock(); // Must be done outside the lock if (isAudio && nextPsc != null) { nextPsc.IsAudioSlot = 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; }
/// <summary> /// Sends a message which announces a change in the player manager. The change concerns a specific player /// slot. This method handles the "player manager messages concerning a special player" message types. /// </summary> /// <param name="type">Type of the message.</param> /// <param name="psc">Player slot controller of the player which is involved.</param> public static void SendPlayerManagerPlayerMessage(MessageType type, IPlayerSlotController psc) { SystemMessage msg = new SystemMessage(type); msg.MessageData[PLAYER_SLOT_CONTROLLER] = psc; ServiceRegistration.Get <IMessageBroker>().Send(CHANNEL, msg); }
protected void CheckCurrentPlayerSlot() { IPlayerManager playerManager = ServiceRegistration.Get <IPlayerManager>(); IPlayerSlotController primaryPSC = playerManager.GetPlayerSlotController(PlayerManagerConsts.PRIMARY_SLOT); IPlayerSlotController secondaryPSC = playerManager.GetPlayerSlotController(PlayerManagerConsts.SECONDARY_SLOT); lock (playerManager.SyncObj) { bool primaryPlayerActive = primaryPSC.IsActive; bool secondaryPlayerActive = secondaryPSC.IsActive; int currentPlayerIndex = _currentPlayerIndex; if (currentPlayerIndex == PlayerManagerConsts.PRIMARY_SLOT && !primaryPlayerActive) { currentPlayerIndex = -1; } else if (currentPlayerIndex == PlayerManagerConsts.SECONDARY_SLOT && !secondaryPlayerActive) { currentPlayerIndex = -1; } if (currentPlayerIndex == -1) { if (primaryPlayerActive) { currentPlayerIndex = PlayerManagerConsts.PRIMARY_SLOT; } } CurrentPlayerIndex = currentPlayerIndex; } }
public override void PrepareVideoPlayer(IPlayerManager playerManager, IList <IPlayerContext> playerContexts, PlayerContextConcurrencyMode concurrencyMode, Guid mediaModuleId, out IPlayerSlotController slotController, ref int audioSlotIndex, ref int currentPlayerIndex) { int numActive = playerContexts.Count; switch (concurrencyMode) { case PlayerContextConcurrencyMode.ConcurrentVideo: if (numActive >= 1 && playerContexts[0].AVType == AVType.Video) { // The primary slot is a video player slot if (numActive == 1) { int slotIndex; playerManager.OpenSlot(out slotIndex, out slotController); playerManager.SwitchSlots(); } else // numActive > 1 { IPlayerContext pc = playerContexts[0]; pc.Reset(); // Necessary to reset the player context to disable the auto close function (pc.CloseWhenFinished) playerManager.ResetSlot(PlayerManagerConsts.PRIMARY_SLOT, out slotController); } audioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; currentPlayerIndex = PlayerManagerConsts.PRIMARY_SLOT; return; } break; } // All other cases are the same as in the default player open strategy base.PrepareVideoPlayer(playerManager, playerContexts, concurrencyMode, mediaModuleId, out slotController, ref audioSlotIndex, ref currentPlayerIndex); }
public override void PrepareVideoPlayer(IPlayerManager playerManager, IList<IPlayerContext> playerContexts, PlayerContextConcurrencyMode concurrencyMode, Guid mediaModuleId, out IPlayerSlotController slotController, ref int audioSlotIndex, ref int currentPlayerIndex) { int numActive = playerContexts.Count; switch (concurrencyMode) { case PlayerContextConcurrencyMode.ConcurrentVideo: if (numActive >= 1 && playerContexts[0].AVType == AVType.Video) { // The primary slot is a video player slot if (numActive == 1) { int slotIndex; playerManager.OpenSlot(out slotIndex, out slotController); playerManager.SwitchSlots(); } else // numActive > 1 { IPlayerContext pc = playerContexts[0]; pc.Reset(); // Necessary to reset the player context to disable the auto close function (pc.CloseWhenFinished) playerManager.ResetSlot(PlayerManagerConsts.PRIMARY_SLOT, out slotController); } audioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; currentPlayerIndex = PlayerManagerConsts.PRIMARY_SLOT; return; } break; } // All other cases are the same as in the default player open strategy base.PrepareVideoPlayer(playerManager, playerContexts, concurrencyMode, mediaModuleId, out slotController, ref audioSlotIndex, ref currentPlayerIndex); }
public bool PreviousItem() { IPlayerSlotController psc = _slotController; if (psc == null) { return(false); } int countLeft = _playlist.ItemList.Count; // Limit number of tries to current playlist size. If the PL doesn't contain any playable item, this avoids an endless loop. MediaItem previousItem; do // Loop: Try until we find an item which is able to play { if (--countLeft < 0 || !_playlist.HasPrevious) // Break loop if we don't have any more items left { return(false); } previousItem = _playlist.MoveAndGetPrevious(); if (previousItem == null) { return(false); } } while (!DoPlay_NoLock(previousItem, StartTime.AtOnce)); return(true); }
private void OnSlotStateChanged(IPlayerSlotController slotController, PlayerSlotState slotState) { if (slotState == PlayerSlotState.Inactive) { Dispose(); } }
public bool ResetSlot(int slotIndex, out IPlayerSlotController slotController) { slotController = null; if (slotIndex == PlayerManagerConsts.SECONDARY_SLOT && !_slots[PlayerManagerConsts.PRIMARY_SLOT].IsActive) { // This is the only invalid constellation because it is not allowed to have the secondary slot active while the primary slot is inactive return(false); } // We don't set a lock because the IsActive property must be set outside the lock. It is no very good solution // to avoid the lock completely but I'll risk it here. Concurrent accesses to the player manager should be avoided // by organizational means. PlayerSlotController psc = _slots[slotIndex]; if (psc.IsActive) { psc.IsActive = false; // Must be done outside the lock } psc.IsActive = true; psc.IsMuted = _isMuted; psc.Volume = _volume; psc.IsAudioSlot = false; if (AudioSlotIndex == -1) { AudioSlotIndex = slotIndex; } slotController = psc; return(true); }
private void CreateScrobbleData(IPlayerSlotController psc) { IPlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null || pc.CurrentMediaItem == null) { return; } IMediaPlaybackControl pmc = pc.CurrentPlayer as IMediaPlaybackControl; if (pmc == null) { return; } var mediaItem = pc.CurrentMediaItem; _duration = pmc.Duration; bool isMovie = mediaItem.Aspects.ContainsKey(MovieAspect.ASPECT_ID); bool isSeries = mediaItem.Aspects.ContainsKey(SeriesAspect.ASPECT_ID); if (isMovie) { _dataMovie = CreateMovieData(mediaItem); } if (isSeries) { _dataEpisode = CreateEpisodeData(mediaItem); } }
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); }
/// <summary> /// Creates or removes <see cref="IIntervalWork"/> from <see cref="IThreadPool"/>. /// </summary> /// <param name="psc">IPlayerSlotController</param> /// <param name="starting"><c>true</c> if starting, <c>false</c> if stopping.</param> /// <returns><c>true</c> if work should be removed when done.</returns> private bool HandleTasks(IPlayerSlotController psc, bool starting) { IThreadPool threadPool = ServiceRegistration.Get <IThreadPool>(); lock (_syncObj) { // On stop, abort background interval work if (!starting && _progressUpdateWorks.ContainsKey(psc)) { threadPool.RemoveIntervalWork(_progressUpdateWorks[psc].Work); return(true); } // When starting, create an asynchronous work and exit here if (!_progressUpdateWorks.ContainsKey(psc)) { IntervalWork work = new IntervalWork(() => HandleScrobble(psc, true), UPDATE_INTERVAL); threadPool.AddIntervalWork(work, false); _progressUpdateWorks[psc] = new PositionWatcher { Work = work }; } } return(false); }
protected void HandlePlayerEnded(IPlayerSlotController psc, uint activationSequence) { IPlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null || !pc.IsValid || psc.ActivationSequence != activationSequence) { return; } if (!pc.NextItem()) { if (pc.CloseWhenFinished) { pc.Close(); } else { psc.Stop(); } if (psc.SlotIndex == PlayerManagerConsts.PRIMARY_SLOT) { StepOutOfPlayerWFState(PlayerWFStateType.FullscreenContent); } if (psc.SlotIndex == CurrentPlayerIndex) { StepOutOfPlayerWFState(PlayerWFStateType.CurrentlyPlaying); } } }
public virtual void PrepareAudioPlayer(IPlayerManager playerManager, IList <IPlayerContext> playerContexts, bool concurrentVideo, Guid mediaModuleId, out IPlayerSlotController slotController, ref int audioSlotIndex, ref int currentPlayerIndex) { if (concurrentVideo) { int numActive = playerManager.NumActiveSlots; // Solve conflicts - close conflicting slots if (numActive > 1) { playerManager.CloseSlot(PlayerManagerConsts.SECONDARY_SLOT); } IPlayerContext pc; if (numActive > 0 && (pc = playerContexts[PlayerManagerConsts.PRIMARY_SLOT]) != null && pc.AVType == AVType.Audio) { playerManager.CloseSlot(PlayerManagerConsts.PRIMARY_SLOT); } } else // !concurrentVideo // Don't enable concurrent controllers: Close all except the primary slot controller { playerManager.CloseAllSlots(); } // Open new slot int slotIndex; playerManager.OpenSlot(out slotIndex, out slotController); audioSlotIndex = slotController.SlotIndex; currentPlayerIndex = slotIndex; }
void OnMessageReceived(AsynchronousMessageQueue queue, SystemMessage message) { if (message.ChannelName == SystemMessaging.CHANNEL) { SystemMessaging.MessageType messageType = (SystemMessaging.MessageType)message.MessageType; ISystemStateService sss = ServiceRegistration.Get <ISystemStateService>(); if (messageType == SystemMessaging.MessageType.SystemStateChanged) { if (sss.CurrentState == SystemState.ShuttingDown || sss.CurrentState == SystemState.Ending) { UnsubscribeFromMessages(); } } } if (message.ChannelName == PlayerManagerMessaging.CHANNEL) { // React to player changes PlayerManagerMessaging.MessageType messageType = (PlayerManagerMessaging.MessageType)message.MessageType; switch (messageType) { case PlayerManagerMessaging.MessageType.PlayerStarted: IPlayerSlotController psc = (IPlayerSlotController)message.MessageData[PlayerManagerMessaging.PLAYER_SLOT_CONTROLLER]; HandleVideoEffectSelection(psc); break; } } }
public virtual void PrepareVideoPlayer(IPlayerManager playerManager, IList <IPlayerContext> playerContexts, PlayerContextConcurrencyMode concurrencyMode, Guid mediaModuleId, out IPlayerSlotController slotController, ref int audioSlotIndex, ref int currentPlayerIndex) { int numActive = playerContexts.Count; int slotIndex; switch (concurrencyMode) { case PlayerContextConcurrencyMode.ConcurrentAudio: if (numActive > 1 && playerContexts[1].AVType == AVType.Audio) { // The secondary slot is an audio player slot slotIndex = PlayerManagerConsts.PRIMARY_SLOT; IPlayerContext pc = playerContexts[0]; pc.Reset(); // Necessary to reset the player context to disable the auto close function (pc.CloseWhenFinished) playerManager.ResetSlot(slotIndex, out slotController); audioSlotIndex = PlayerManagerConsts.SECONDARY_SLOT; } else if (numActive == 1 && playerContexts[0].AVType == AVType.Audio) { // The primary slot is an audio player slot playerManager.OpenSlot(out slotIndex, out slotController); // Make new video slot the primary slot playerManager.SwitchSlots(); audioSlotIndex = PlayerManagerConsts.SECONDARY_SLOT; } else { // No audio slot available playerManager.CloseAllSlots(); playerManager.OpenSlot(out slotIndex, out slotController); audioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; } break; case PlayerContextConcurrencyMode.ConcurrentVideo: if (numActive >= 1 && playerContexts[0].AVType == AVType.Video) { // The primary slot is a video player slot if (numActive > 1) { playerManager.CloseSlot(PlayerManagerConsts.SECONDARY_SLOT); } playerManager.OpenSlot(out slotIndex, out slotController); audioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; } else { playerManager.CloseAllSlots(); playerManager.OpenSlot(out slotIndex, out slotController); audioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; } break; default: // Don't enable concurrent controllers: Close all except the primary slot controller playerManager.CloseAllSlots(); playerManager.OpenSlot(out slotIndex, out slotController); audioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; break; } currentPlayerIndex = slotIndex; }
/// <summary> /// Sends a message which announces the player has been stopped. /// </summary> /// <param name="position">The position at which playback was stopped.</param> /// <param name="psc">Player slot controller of the player which was stopped.</param> public static void SendPlayerStoppedMessage(TimeSpan?position, IPlayerSlotController psc) { SystemMessage msg = new SystemMessage(MessageType.PlayerStopped); msg.MessageData[PLAYER_SLOT_CONTROLLER] = psc; msg.MessageData[PLAYER_POSITION] = position; ServiceRegistration.Get <IMessageBroker>().Send(CHANNEL, msg); }
public const string ACTIVATION_SEQUENCE = "ActivationSequence"; // Holds the activation sequence number of the player slot controller at the time when the message was sent (uint) /// <summary> /// Sends a message which announces a change in a specific player. This method handles all /// the "player messages" message types. /// </summary> /// <param name="type">Type of the message.</param> /// <param name="psc">Player slot controller of the player which was changed.</param> public static void SendPlayerMessage(MessageType type, IPlayerSlotController psc) { SystemMessage msg = new SystemMessage(type); msg.MessageData[PLAYER_SLOT_CONTROLLER] = psc; msg.MessageData[ACTIVATION_SEQUENCE] = psc.ActivationSequence; ServiceRegistration.Get <IMessageBroker>().Send(CHANNEL, msg); }
protected override IVideoPlayer GetPlayerToSynchronize() { IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>(); IPlayerSlotController backgroundPsc = VideoBackgroundModel.GetCurrentInstance().PlayerSlotController; IVideoPlayer player = backgroundPsc != null ? backgroundPsc.CurrentPlayer as IVideoPlayer : null; return(playerContextManager[PlayerContextIndex.PRIMARY] as IVideoPlayer ?? player); }
/// <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); }
protected void HandleRequestNextItem(IPlayerSlotController psc) { PlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null || !pc.IsActive) { return; } pc.RequestNextItem_NoLock(); }
public void EndBackgroundPlayback() { if (_backgroundPsc != null) { IPlayerManager playerManager = ServiceRegistration.Get <IPlayerManager>(); playerManager.CloseSlot(_backgroundPsc); _backgroundPsc = null; VideoPlayer = null; } }
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; } }
protected void HandleRequestNextItem(IPlayerSlotController psc, uint activationSequence) { PlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null || !pc.IsValid || psc.ActivationSequence != activationSequence) { return; } pc.RequestNextItem_NoLock(); }
public virtual void PrepareVideoPlayer(IPlayerManager playerManager, IList<IPlayerContext> playerContexts, PlayerContextConcurrencyMode concurrencyMode, Guid mediaModuleId, out IPlayerSlotController slotController, ref int audioSlotIndex, ref int currentPlayerIndex) { int numActive = playerContexts.Count; int slotIndex; switch (concurrencyMode) { case PlayerContextConcurrencyMode.ConcurrentAudio: if (numActive > 1 && playerContexts[1].AVType == AVType.Audio) { // The secondary slot is an audio player slot slotIndex = PlayerManagerConsts.PRIMARY_SLOT; IPlayerContext pc = playerContexts[0]; pc.Reset(); // Necessary to reset the player context to disable the auto close function (pc.CloseWhenFinished) playerManager.ResetSlot(slotIndex, out slotController); audioSlotIndex = PlayerManagerConsts.SECONDARY_SLOT; } else if (numActive == 1 && playerContexts[0].AVType == AVType.Audio) { // The primary slot is an audio player slot playerManager.OpenSlot(out slotIndex, out slotController); // Make new video slot the primary slot playerManager.SwitchSlots(); audioSlotIndex = PlayerManagerConsts.SECONDARY_SLOT; } else { // No audio slot available playerManager.CloseAllSlots(); playerManager.OpenSlot(out slotIndex, out slotController); audioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; } break; case PlayerContextConcurrencyMode.ConcurrentVideo: if (numActive >= 1 && playerContexts[0].AVType == AVType.Video) { // The primary slot is a video player slot if (numActive > 1) playerManager.CloseSlot(PlayerManagerConsts.SECONDARY_SLOT); playerManager.OpenSlot(out slotIndex, out slotController); audioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; } else { playerManager.CloseAllSlots(); playerManager.OpenSlot(out slotIndex, out slotController); audioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; } break; default: // Don't enable concurrent controllers: Close all except the primary slot controller playerManager.CloseAllSlots(); playerManager.OpenSlot(out slotIndex, out slotController); audioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; break; } currentPlayerIndex = slotIndex; }
public void ResetContextVariable(string key) { IPlayerSlotController psc = _slotController; if (psc == null) { return; } lock (SyncObj) psc.ContextVariables.Remove(key); }
public void SetContextVariable(string key, object value) { IPlayerSlotController psc = _slotController; if (psc == null) { return; } lock (SyncObj) psc.ContextVariables[key] = value; }
protected IPlayer GetCurrentPlayer() { IPlayerSlotController psc = _slotController; if (psc == null) { return(null); } lock (SyncObj) return(psc.IsActive ? psc.CurrentPlayer : null); }
protected void HandleRequestNextItem(IPlayerSlotController psc) { PlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null || !pc.IsActive) { return; } HandleProgress(TimeSpan.FromSeconds(-1), pc.CurrentMediaItem, true).Wait(); pc.RequestNextItem_NoLock(); }
protected IPlayer GetCurrentPlayer() { IPlayerSlotController psc = _slotController; if (psc == null) { return(null); } lock (SyncObj) return(psc.IsClosed ? null : psc.CurrentPlayer); }
internal PlayerContext(IPlayerSlotController slotController, Guid mediaModuleId, string name, AVType type, Guid currentlyPlayingWorkflowStateId, Guid fullscreenContentWorkflowStateId) { _slotController = slotController; _slotController.Closed += OnClosed; SetContextVariable(KEY_PLAYER_CONTEXT, this); _playlist = new Playlist(this); _mediaModuleId = mediaModuleId; _name = name; _type = type; _currentlyPlayingWorkflowStateId = currentlyPlayingWorkflowStateId; _fullscreenContentWorkflowStateId = fullscreenContentWorkflowStateId; }
public static void ReallocGUIResources(IPlayerSlotController psc) { ISharpDXVideoPlayer sdvp = psc.CurrentPlayer as ISharpDXVideoPlayer; if (sdvp == null) return; try { sdvp.ReallocGUIResources(); } catch (Exception e) { ServiceRegistration.Get<ILogger>().Error("Problem reallocating GUI resources in player '{0}'", e, sdvp); } }
public virtual void PrepareAudioPlayer(IPlayerManager playerManager, IList<IPlayerContext> playerContexts, bool concurrentVideo, Guid mediaModuleId, out IPlayerSlotController slotController, ref int audioSlotIndex, ref int currentPlayerIndex) { if (concurrentVideo) { int numActive = playerManager.NumActiveSlots; // Solve conflicts - close conflicting slots if (numActive > 1) playerManager.CloseSlot(PlayerManagerConsts.SECONDARY_SLOT); IPlayerContext pc; if (numActive > 0 && (pc = playerContexts[PlayerManagerConsts.PRIMARY_SLOT]) != null && pc.AVType == AVType.Audio) playerManager.CloseSlot(PlayerManagerConsts.PRIMARY_SLOT); } else // !concurrentVideo // Don't enable concurrent controllers: Close all except the primary slot controller playerManager.CloseAllSlots(); // Open new slot int slotIndex; playerManager.OpenSlot(out slotIndex, out slotController); audioSlotIndex = slotController.SlotIndex; currentPlayerIndex = slotIndex; }
protected void HandleRequestNextItem(IPlayerSlotController psc, uint activationSequence) { PlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null || !pc.IsValid || psc.ActivationSequence != activationSequence) return; pc.RequestNextItem_NoLock(); }
private void OnSlotStateChanged(IPlayerSlotController slotController, PlayerSlotState slotState) { if (slotState == PlayerSlotState.Inactive) Dispose(); }
public void Reset() { lock (SyncObj) { IPlayerSlotController slotController = _slotController; if (slotController == null) return; slotController.SlotStateChanged -= OnSlotStateChanged; if (slotController.IsActive) ResetContextVariable(KEY_PLAYER_CONTEXT); _slotController = null; } }
private void Info(IPlayerSlotController psc ) { IPlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null) return; var artist = string.Empty; var title = psc.CurrentPlayer.MediaItemTitle; List<string> value; if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, AudioAspect.ATTR_ARTISTS, out value)) artist = value[0]; var rec = Sites.MusicBrainz.Get.SongIds(artist, title); if (rec.MbRecord.Count > 0) { var artistId = string.Empty; var songId = string.Empty; if (rec.MbRecord[0].ArtistssArtistses.Count > 0) { artistId = rec.MbRecord[0].ArtistssArtistses[0].Artist.Id; } if (rec.MbRecord[0].Releases.Count > 0) { songId = rec.MbRecord[0].Releases[0].Id; } var a = new Artists(); a = Sites.TheAudioDB.Get.ArtistInfoByMbid(artistId); var ar = new Dictionary<string, Sites.Fanart_tv.Artist>(); ar = Sites.Fanart_tv.Get.ArtistInfo(artistId); var fanarts = new List<string>(); if (a.artists.Count > 0) { if (a.artists[0].ArtistFanart1 != "") fanarts.Add(a.artists[0].ArtistFanart1); if (a.artists[0].ArtistFanart2 != "") fanarts.Add(a.artists[0].ArtistFanart2); if (a.artists[0].ArtistFanart3 != "") fanarts.Add(a.artists[0].ArtistFanart3); } if (ar.Count <= 0) return; foreach (var pair in ar) { fanarts.AddRange(pair.Value.ArtistBackground.Select(t => t.Url)); } if (fanarts.Count > 0) { var fanArtBgModel = (FanArtBackgroundModel)ServiceRegistration.Get<IWorkflowManager>().GetModel(FanArtBackgroundModel.FANART_MODEL_ID); if (fanArtBgModel != null) { fanArtBgModel.ImageSource = new MultiImageSource { UriSource = fanarts[0] }; } } else { noFanart(); } } }
private void CreateScrobbleData(IPlayerSlotController psc) { IPlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null || pc.CurrentMediaItem == null) return; IMediaPlaybackControl pmc = pc.CurrentPlayer as IMediaPlaybackControl; if (pmc == null) return; var mediaItem = pc.CurrentMediaItem; _duration = pmc.Duration; bool isMovie = mediaItem.Aspects.ContainsKey(MovieAspect.ASPECT_ID); bool isSeries = mediaItem.Aspects.ContainsKey(SeriesAspect.ASPECT_ID); if (isMovie) _dataMovie = CreateMovieData(mediaItem); if (isSeries) _dataEpisode = CreateEpisodeData(mediaItem); }
public void CloseSlot(IPlayerSlotController playerSlotController) { PlayerSlotController psc = playerSlotController as PlayerSlotController; if (psc == null) return; bool isAudio = psc.IsAudioSlot && !psc.IsClosed; PlayerSlotController nextPsc; lock (_syncObj) { int nextIndex = _slots.IndexOf(psc); _slots.Remove(psc); int numSlots = _slots.Count; nextIndex = numSlots == 0 ? 0 : (nextIndex + 1) % numSlots; nextPsc = numSlots > nextIndex ? _slots[nextIndex] : null; } psc.Close_NoLock(); // Must be done outside the lock if (isAudio && nextPsc != null) nextPsc.IsAudioSlot = true; }
public void EndBackgroundPlayback() { if (_backgroundPsc != null) { IPlayerManager playerManager = ServiceRegistration.Get<IPlayerManager>(); playerManager.CloseSlot(_backgroundPsc); _backgroundPsc = null; VideoPlayer = null; } }
/// <summary> /// Creates or removes <see cref="IIntervalWork"/> from <see cref="IThreadPool"/>. /// </summary> /// <param name="psc">IPlayerSlotController</param> /// <param name="starting"><c>true</c> if starting, <c>false</c> if stopping.</param> /// <returns><c>true</c> if work should be removed when done.</returns> private bool HandleTasks(IPlayerSlotController psc, bool starting) { IThreadPool threadPool = ServiceRegistration.Get<IThreadPool>(); lock (_syncObj) { // On stop, abort background interval work if (!starting && _progressUpdateWorks.ContainsKey(psc)) { threadPool.RemoveIntervalWork(_progressUpdateWorks[psc].Work); return true; } // When starting, create an asynchronous work and exit here if (!_progressUpdateWorks.ContainsKey(psc)) { IntervalWork work = new IntervalWork(() => HandleScrobble(psc, true), UPDATE_INTERVAL); threadPool.AddIntervalWork(work, false); _progressUpdateWorks[psc] = new PositionWatcher { Work = work }; } } return false; }
public const string ACTIVATION_SEQUENCE = "ActivationSequence"; // Holds the activation sequence number of the player slot controller at the time when the message was sent (uint) /// <summary> /// Sends a message which announces a change in a specific player. This method handles all /// the "player messages" message types. /// </summary> /// <param name="type">Type of the message.</param> /// <param name="psc">Player slot controller of the player which was changed.</param> public static void SendPlayerMessage(MessageType type, IPlayerSlotController psc) { SystemMessage msg = new SystemMessage(type); msg.MessageData[PLAYER_SLOT_CONTROLLER] = psc; msg.MessageData[ACTIVATION_SEQUENCE] = psc.ActivationSequence; ServiceRegistration.Get<IMessageBroker>().Send(CHANNEL, msg); }
public bool OpenSlot(out int slotIndex, out IPlayerSlotController slotController) { slotIndex = -1; slotController = null; lock (_syncObj) { // Find a free slot if (!_slots[PlayerManagerConsts.PRIMARY_SLOT].IsActive) slotIndex = PlayerManagerConsts.PRIMARY_SLOT; else if (!_slots[PlayerManagerConsts.SECONDARY_SLOT].IsActive) slotIndex = PlayerManagerConsts.SECONDARY_SLOT; else return false; return ResetSlot(slotIndex, out slotController); } }
public bool ResetSlot(int slotIndex, out IPlayerSlotController slotController) { slotController = null; if (slotIndex == PlayerManagerConsts.SECONDARY_SLOT && !_slots[PlayerManagerConsts.PRIMARY_SLOT].IsActive) // This is the only invalid constellation because it is not allowed to have the secondary slot active while the primary slot is inactive return false; // We don't set a lock because the IsActive property must be set outside the lock. It is no very good solution // to avoid the lock completely but I'll risk it here. Concurrent accesses to the player manager should be avoided // by organizational means. PlayerSlotController psc = _slots[slotIndex]; if (psc.IsActive) psc.IsActive = false; // Must be done outside the lock psc.IsActive = true; psc.IsMuted = _isMuted; psc.Volume = _volume; psc.IsAudioSlot = false; if (AudioSlotIndex == -1) AudioSlotIndex = slotIndex; slotController = psc; return true; }
public static PlayerContext GetPlayerContext(IPlayerSlotController psc) { if (psc == null) return null; IPlayerManager playerManager = ServiceRegistration.Get<IPlayerManager>(); lock (playerManager.SyncObj) { if (psc.IsClosed) return null; object result; if (psc.ContextVariables.TryGetValue(KEY_PLAYER_CONTEXT, out result)) return result as PlayerContext; } return null; }
public void StartBackgroundPlayback() { if (!IsEnabled) return; IScreenControl screenControl = ServiceRegistration.Get<IScreenControl>(); IVideoPlayerSynchronizationStrategy current = screenControl.VideoPlayerSynchronizationStrategy; if (current != _backgroundPlayerStrategy) // We replace the default strategy with our own to prefer the video background player. screenControl.VideoPlayerSynchronizationStrategy = _backgroundPlayerStrategy; IPlayerManager playerManager = ServiceRegistration.Get<IPlayerManager>(); if (_backgroundPsc == null) _backgroundPsc = playerManager.OpenSlot(); if (_backgroundPsc == null) return; // If we already have a player active, don't start a new one. IPlayer currentPlayer = _backgroundPsc.CurrentPlayer; if (currentPlayer != null && currentPlayer.State == PlayerState.Active) return; try { _backgroundPsc.Play(_video, StartTime.AtOnce); BaseDXPlayer player = _backgroundPsc.CurrentPlayer as BaseDXPlayer; if (player != null) player.AutoRepeat = true; VideoPlayer = player as ISharpDXVideoPlayer; } catch (Exception ex) { ServiceRegistration.Get<ILogger>().Error("VideoBackgroundModel: Error opening MediaItem {0} for background playback!", ex, _videoFilename); } }
/// <summary> /// Creates Scrobble data based on a DBMovieInfo object /// </summary> /// <param name="psc"></param> /// <param name="pc">PlayerContext</param> /// <param name="starting"></param> /// <param name="scrobbleData"></param> /// <param name="state"></param> /// <returns>The Trakt scrobble data to send</returns> private bool TryCreateScrobbleData(IPlayerSlotController psc, IPlayerContext pc, bool starting, out AbstractScrobble scrobbleData, out TraktScrobbleStates state) { scrobbleData = null; state = starting ? TraktScrobbleStates.watching : TraktScrobbleStates.scrobble; if (_settings.Settings.Authentication == null) return false; string username = _settings.Settings.Authentication.Username; string password = _settings.Settings.Authentication.Password; if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) return false; // For canceling the watching, it is to have no TraktMovieScrobble. if (pc.CurrentMediaItem == null) { if (starting) return false; state = TraktScrobbleStates.cancelwatching; return true; } bool isMovie = pc.CurrentMediaItem.Aspects.ContainsKey(MovieAspect.ASPECT_ID); bool isSeries = pc.CurrentMediaItem.Aspects.ContainsKey(SeriesAspect.ASPECT_ID); if (!isMovie && !isSeries) return false; string title = pc.CurrentPlayer != null ? pc.CurrentPlayer.MediaItemTitle : null; IMediaPlaybackControl pmc = pc.CurrentPlayer as IMediaPlaybackControl; TimeSpan currentPosition; if (pmc != null) { _progressUpdateWorks[psc].Duration = pmc.Duration; currentPosition = pmc.CurrentTime; } else { // Player is already removed on stopping, so take the resume position if available currentPosition = _progressUpdateWorks[psc].ResumePosition; } int progress = currentPosition == TimeSpan.Zero ? (starting ? 0 : 100) : Math.Min((int)(currentPosition.TotalSeconds * 100 / _progressUpdateWorks[psc].Duration.TotalSeconds), 100); string value; int iValue; DateTime dtValue; long lValue; if (isMovie) { TraktMovieScrobble movie = new TraktMovieScrobble(); if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, MovieAspect.ATTR_IMDB_ID, out value) && !string.IsNullOrWhiteSpace(value)) movie.IMDBID = value; if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, MovieAspect.ATTR_TMDB_ID, out iValue) && iValue > 0) movie.TMDBID = iValue.ToString(); if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, MediaAspect.ATTR_RECORDINGTIME, out dtValue)) movie.Year = dtValue.Year.ToString(); if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, MovieAspect.ATTR_RUNTIME_M, out iValue) && iValue > 0) movie.Duration = iValue.ToString(); scrobbleData = movie; } if (isSeries) { TraktEpisodeScrobble series = new TraktEpisodeScrobble(); if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_IMDB_ID, out value) && !string.IsNullOrWhiteSpace(value)) series.IMDBID = value; if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_TVDB_ID, out iValue)) series.SeriesID = iValue.ToString(); if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_SERIESNAME, out value) && !string.IsNullOrWhiteSpace(value)) series.Title = value; if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_FIRSTAIRED, out dtValue)) series.Year = dtValue.Year.ToString(); if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_SEASON, out iValue)) series.Season = iValue.ToString(); List<int> intList; if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_EPISODE, out intList) && intList.Any()) series.Episode = intList.First().ToString(); // TODO: multi episode files?! scrobbleData = series; } // Fallback duration info if (string.IsNullOrWhiteSpace(scrobbleData.Duration) && MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, VideoAspect.ATTR_DURATION, out lValue) && lValue > 0) scrobbleData.Duration = (lValue / 60).ToString(); if (string.IsNullOrWhiteSpace(scrobbleData.Title)) scrobbleData.Title = title; scrobbleData.Progress = progress.ToString(); if (!starting && progress < WATCHED_PERCENT) state = TraktScrobbleStates.cancelwatching; scrobbleData.PluginVersion = TraktSettings.Version; scrobbleData.MediaCenter = "MediaPortal 2"; scrobbleData.MediaCenterVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(); scrobbleData.MediaCenterBuildDate = String.Empty; scrobbleData.Username = username; scrobbleData.Password = password; return true; }
protected void HandlePlayerStopped(IPlayerSlotController psc, uint activationSequence) { IPlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null || !pc.IsValid || psc.ActivationSequence != activationSequence) return; // We get the player message asynchronously, so we have to check the state of the slot again to ensure // we close the correct one if (pc.CloseWhenFinished && pc.CurrentPlayer == null) pc.Close(); if (psc.SlotIndex == PlayerManagerConsts.PRIMARY_SLOT) StepOutOfPlayerWFState(PlayerWFStateType.FullscreenContent); if (psc.SlotIndex == CurrentPlayerIndex) StepOutOfPlayerWFState(PlayerWFStateType.CurrentlyPlaying); }
public void CloseSlot(IPlayerSlotController playerSlotController) { PlayerSlotController psc = playerSlotController as PlayerSlotController; if (psc == null) return; bool isAudio = psc.IsActive && psc.IsAudioSlot; psc.IsActive = false; // Must be done outside the lock CleanupSlotOrder(); if (isAudio) AudioSlotIndex = PlayerManagerConsts.PRIMARY_SLOT; }
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 HandleScrobble(IPlayerSlotController psc, bool starting) { try { IPlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null) return; bool removePsc = HandleTasks(psc, starting); AbstractScrobble scrobbleData; TraktScrobbleStates state; if (TryCreateScrobbleData(psc, pc, starting, out scrobbleData, out state)) { ServiceRegistration.Get<ILogger>().Debug("Trakt.tv: [{5}] {0}, Duration {1}, Percent {2}, PSC.Duration {3}, PSC.ResumePosition {4}", scrobbleData.Title, scrobbleData.Duration, scrobbleData.Progress, _progressUpdateWorks[psc].Duration, _progressUpdateWorks[psc].ResumePosition, state); TraktMovieScrobble movie = scrobbleData as TraktMovieScrobble; if (movie != null) TraktAPI.ScrobbleMovieState(movie, state); TraktEpisodeScrobble episode = scrobbleData as TraktEpisodeScrobble; if (episode != null) TraktAPI.ScrobbleEpisodeState(episode, state); } if (removePsc) lock (_syncObj) _progressUpdateWorks.Remove(psc); } catch (ThreadAbortException) { } catch (Exception ex) { ServiceRegistration.Get<ILogger>().Error("Trakt.tv: Exception while scrobbling", ex); } }
/// <summary> /// Sends a message which announces a change in the player manager. The change concerns a specific player /// slot. This method handles the "player manager messages concerning a special player" message types. /// </summary> /// <param name="type">Type of the message.</param> /// <param name="psc">Player slot controller of the player which is involved.</param> public static void SendPlayerManagerPlayerMessage(MessageType type, IPlayerSlotController psc) { SystemMessage msg = new SystemMessage(type); msg.MessageData[PLAYER_SLOT_CONTROLLER] = psc; ServiceRegistration.Get<IMessageBroker>().Send(CHANNEL, msg); }
protected void HandlePlayerEnded(IPlayerSlotController psc, uint activationSequence) { IPlayerContext pc = PlayerContext.GetPlayerContext(psc); if (pc == null || !pc.IsValid || psc.ActivationSequence != activationSequence) return; if (!pc.NextItem()) { if (pc.CloseWhenFinished) pc.Close(); else psc.Stop(); if (psc.SlotIndex == PlayerManagerConsts.PRIMARY_SLOT) StepOutOfPlayerWFState(PlayerWFStateType.FullscreenContent); if (psc.SlotIndex == CurrentPlayerIndex) StepOutOfPlayerWFState(PlayerWFStateType.CurrentlyPlaying); } }
public IPlayerSlotController Revoke() { lock (SyncObj) { IPlayerSlotController slotController = _slotController; _slotController = null; if (slotController == null) return null; slotController.Closed -= OnClosed; ResetContextVariable(KEY_PLAYER_CONTEXT); return slotController; } }
/// <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 OnClosed(IPlayerSlotController slotController) { Revoke(); }
private void HandleVideoEffectSelection(IPlayerSlotController psc) { ISharpDXVideoPlayer player = psc.CurrentPlayer as ISharpDXVideoPlayer; if (player == null) return; lock (player.SurfaceLock) { if (player.Texture == null) return; var videoFrameHeight = player.VideoSize.Height; player.EffectOverride = videoFrameHeight <= _settings.Settings.ResolutionLimit ? _settings.Settings.LowerResolutionEffect : _settings.Settings.HigherResolutionEffect; } }