示例#1
0
        private bool CallPlayMediaUsingMediaCollection(MediaCenterEnvironment mediaCenterEnvironment, PlayableItem playable)
        {
            var coll = new MediaCollection();

            // Create a MediaCollectionItem for each file to play
            if (playable.HasMediaItems)
            {
                PlaybackControllerHelper.PopulateMediaCollectionUsingMediaItems(this, coll, playable);
            }
            else
            {
                PlaybackControllerHelper.PopulateMediaCollectionUsingFiles(coll, playable);
            }

            // Set starting position if we're resuming
            if (playable.Resume)
            {
                var playstate = playable.MediaItems.First().PlaybackStatus;

                coll.CurrentIndex = playstate.PlaylistPosition;
                coll[playstate.PlaylistPosition].Start = new TimeSpan(playstate.PositionTicks);
            }

            CurrentMediaCollection = coll;

            bool success = PlaybackControllerHelper.CallPlayMedia(mediaCenterEnvironment, MediaType.MediaCollection, CurrentMediaCollection, false);

            if (!success)
            {
                CurrentMediaCollection = null;
            }

            return(success);
        }
        /// <summary>
        /// Handles a change of Playstate by firing various events and post play processes
        /// </summary>
        private void HandleStoppedState(MediaCenterEnvironment env, MediaExperience exp, MediaTransport transport, PlaybackStateEventArgs e)
        {
            // Stop listening to the events
            env.PropertyChanged       -= MediaCenterEnvironment_PropertyChanged;
            transport.PropertyChanged -= MediaTransport_PropertyChanged;

            // This will prevent us from getting in here twice after playback stops and calling post-play processes more than once.
            _HasStartedPlaying = false;

            _CurrentMediaCollection = null;

            var mediaType = exp.MediaType;

            // Check if internal wmc player is still playing, which could happen if the user launches live tv while playing something
            if (mediaType != Microsoft.MediaCenter.Extensibility.MediaType.TV)
            {
                Application.CurrentInstance.ShowNowPlaying = false;

                if (mediaType == Microsoft.MediaCenter.Extensibility.MediaType.Audio || mediaType == Microsoft.MediaCenter.Extensibility.MediaType.DVD)
                {
                    PlaybackControllerHelper.ReturnToApplication(true);
                }
            }

            // Fire the OnFinished event for each item
            OnPlaybackFinished(e);
        }
        /// <summary>
        /// Retrieves the current playback item using properties from MediaExperience and Transport
        /// </summary>
        private PlaybackStateEventArgs GetCurrentPlaybackState(string metadataTitle, long metadataDuration, long positionTicks)
        {
            int          filePlaylistPosition;
            int          currentMediaIndex;
            PlayableItem currentPlayableItem;

            if (_CurrentMediaCollection == null)
            {
                currentPlayableItem = PlaybackControllerHelper.GetCurrentPlaybackItemUsingMetadataTitle(this, CurrentPlayableItems, metadataTitle, out filePlaylistPosition, out currentMediaIndex);
            }
            else
            {
                currentPlayableItem = PlaybackControllerHelper.GetCurrentPlaybackItemFromMediaCollection(CurrentPlayableItems, _CurrentMediaCollection, out filePlaylistPosition, out currentMediaIndex);

                // When playing multiple files with MediaCollections, if you allow playback to finish, CurrentIndex will be reset to 0, but transport.Position will be equal to the duration of the last item played
                if (filePlaylistPosition == 0 && positionTicks >= metadataDuration)
                {
                    positionTicks = 0;
                }
            }

            return(new PlaybackStateEventArgs()
            {
                Position = positionTicks,
                CurrentFileIndex = filePlaylistPosition,
                DurationFromPlayer = metadataDuration,
                Item = currentPlayableItem,
                CurrentMediaIndex = currentMediaIndex
            });
        }
        /// <summary>
        /// Moves the player to a given position
        /// </summary>
        protected override void SeekInternal(long position)
        {
            var mce = AddInHost.Current.MediaCenterEnvironment;

            Logger.ReportVerbose("Trying to seek position :" + new TimeSpan(position).ToString());
            PlaybackControllerHelper.WaitForStream(mce);
            mce.MediaExperience.Transport.Position = new TimeSpan(position);
        }
示例#5
0
        /// <summary>
        /// Unpauses playback
        /// </summary>
        protected override void UnPauseInternal()
        {
            var transport = PlaybackControllerHelper.GetCurrentMediaTransport();

            if (transport != null)
            {
                transport.PlayRate = 2;
            }
        }
示例#6
0
        protected override void Dispose(bool isDisposing)
        {
            MediaTransport transport = PlaybackControllerHelper.GetCurrentMediaTransport();

            if (transport != null)
            {
                transport.PropertyChanged -= MediaTransport_PropertyChanged;
            }

            base.Dispose(isDisposing);
        }
        /// <summary>
        /// Calls PlayMedia
        /// </summary>
        private bool CallPlayMediaLegacy(MediaCenterEnvironment mediaCenterEnvironment, PlayableItem playable)
        {
            Microsoft.MediaCenter.MediaType type = PlaybackControllerHelper.GetMediaType(playable);

            bool playedWithPlaylist = false;

            // Need to create a playlist
            if (PlaybackControllerHelper.RequiresWPL(playable))
            {
                IEnumerable <string> files = playable.FilesFormattedForPlayer;

                string playlistFile = PlaybackControllerHelper.CreateWPLPlaylist(playable.Id.ToString(), files, playable.StartPlaylistPosition);

                if (!PlaybackControllerHelper.CallPlayMedia(mediaCenterEnvironment, type, playlistFile, false))
                {
                    return(false);
                }

                playedWithPlaylist = true;
            }

            // If we're playing a dvd and the last item played was a MediaCollection, we need to make sure the MediaCollection has
            // fully cleared out of the player or there will be quirks such as ff/rew remote buttons not working
            if (playable.HasMediaItems)
            {
                Video video = playable.MediaItems.First() as Video;

                Microsoft.MediaCenter.Extensibility.MediaType lastMediaType = PlaybackControllerHelper.GetCurrentMediaType();

                if (video != null && video.MediaType == Library.MediaType.DVD && (lastMediaType == Microsoft.MediaCenter.Extensibility.MediaType.MediaCollection || lastMediaType == Microsoft.MediaCenter.Extensibility.MediaType.Unknown))
                {
                    System.Threading.Thread.Sleep(500);
                }
            }

            if (!playedWithPlaylist)
            {
                bool queue = false;

                foreach (string fileToPlay in playable.FilesFormattedForPlayer)
                {
                    if (!PlaybackControllerHelper.CallPlayMedia(mediaCenterEnvironment, type, fileToPlay, queue))
                    {
                        return(false);
                    }

                    queue = true;
                }
            }

            return(true);
        }
示例#8
0
 /// <summary>
 /// Calls PlayMedia using either a MediaCollection or a single file
 /// </summary>
 private bool CallPlayMediaForPlayableItem(MediaCenterEnvironment mediaCenterEnvironment, PlayableItem playable)
 {
     if (PlaybackControllerHelper.UseLegacyApi(playable))
     {
         bool success = CallPlayMediaLegacy(mediaCenterEnvironment, playable);
         CurrentMediaCollection = null;
         return(success);
     }
     else
     {
         return(CallPlayMediaUsingMediaCollection(mediaCenterEnvironment, playable));
     }
 }
示例#9
0
 /// <summary>
 /// Moves the player to a given position
 /// </summary>
 protected override void SeekInternal(long position)
 {
     try
     {
         Logger.ReportVerbose("Trying to seek position :" + new TimeSpan(position).ToString());
         PlaybackControllerHelper.WaitForStream(Application.MediaExperience);
         Application.MediaExperience.Transport.Position = new TimeSpan(position);
     }
     catch (Exception e)
     {
         Logger.ReportException("Error attempting to seek", e);
     }
 }
        public void StopIfOutOfScope(BaseItem item)
        {
            if (!IsPlaying)
            {
                return;
            }

            //if the passed in item is our current scope or our current scope is a parent then we are still in scope and continue playing
            if (item != CurrentScope && !IsParent(CurrentScope, item))
            {
                PlaybackControllerHelper.Stop();
            }
        }
示例#11
0
        /// <summary>
        /// When playback is based purely on files, this will take the files that were supplied to the PlayableItem,
        /// and create the actual paths that will be sent to the player
        /// </summary>
        internal override IEnumerable <string> GetPlayableFiles(IEnumerable <string> files)
        {
            foreach (string file in files)
            {
                MediaBrowser.Library.MediaType mediaType = MediaBrowser.Library.MediaTypeResolver.DetermineType(file);

                if (mediaType == Library.MediaType.BluRay)
                {
                    yield return(PlaybackControllerHelper.GetBluRayPath(file));
                }

                yield return(ShouldTranscode ? PlaybackControllerHelper.GetTranscodedPath(file) : file);
            }
        }
        /// <summary>
        /// Puts the player into fullscreen mode
        /// </summary>
        public override void GoToFullScreen()
        {
            var mce = MediaExperience ?? PlaybackControllerHelper.GetMediaExperienceUsingReflection();

            if (mce != null)
            {
                Logger.ReportVerbose("Going fullscreen...");
                mce.GoToFullScreen();
            }
            else
            {
                Logger.ReportError("AddInHost.Current.MediaCenterEnvironment.MediaExperience is null, we have no way to go full screen!");
                AddInHost.Current.MediaCenterEnvironment.Dialog(Application.CurrentInstance.StringData("CannotMaximizeDial"), "", Microsoft.MediaCenter.DialogButtons.Ok, 0, true);
            }
        }
示例#13
0
        /// <summary>
        /// Takes a Media object and returns the list of files that will be sent to the player
        /// </summary>
        internal override IEnumerable <string> GetPlayableFiles(Media media)
        {
            IEnumerable <string> files = base.GetPlayableFiles(media);

            Video video = media as Video;

            if (video != null)
            {
                if (video.MediaType == Library.MediaType.BluRay)
                {
                    files = files.Select(i => PlaybackControllerHelper.GetBluRayPath(i));
                }
            }

            return(ShouldTranscode ? files.Select(f => PlaybackControllerHelper.GetTranscodedPath(f)) : files);
        }
示例#14
0
 private void QueuePlayableItemIntoMediaCollection(PlayableItem playable)
 {
     try
     {
         // Create a MediaCollectionItem for each file to play
         if (playable.HasMediaItems)
         {
             PlaybackControllerHelper.PopulateMediaCollectionUsingMediaItems(this, CurrentMediaCollection, playable);
         }
         else
         {
             PlaybackControllerHelper.PopulateMediaCollectionUsingFiles(CurrentMediaCollection, playable);
         }
     }
     catch (Exception ex)
     {
         OnErrorPlayingItem(playable, ex);
     }
 }
        private void QueuePlayableItemLegacy(PlayableItem playable)
        {
            Microsoft.MediaCenter.MediaType type = MediaType.Audio;

            bool success = true;

            foreach (string file in playable.FilesFormattedForPlayer)
            {
                if (!PlaybackControllerHelper.CallPlayMedia(AddInHost.Current.MediaCenterEnvironment, type, file, true))
                {
                    success = false;
                    break;
                }
            }

            if (!success)
            {
                OnErrorPlayingItem(playable, "PlayMedia returned false");
            }
        }
示例#16
0
        /// <summary>
        /// Handles a change of Playstate by firing various events and post play processes
        /// </summary>
        private void HandleStoppedState(MediaCenterEnvironment env, MediaExperience exp, MediaTransport transport, PlaybackStateEventArgs e)
        {
            Logger.ReportVerbose("In HandleStoppedState");
            // Stop listening to the events
            env.PropertyChanged       -= MediaCenterEnvironment_PropertyChanged;
            transport.PropertyChanged -= MediaTransport_PropertyChanged;

            Logger.ReportVerbose("Events unhooked");

            // This will prevent us from getting in here twice after playback stops and calling post-play processes more than once.
            _HasStartedPlaying = false;

            CurrentMediaCollection = null;

            var mediaType = exp.MediaType;


            // Check if internal wmc player is still playing, which could happen if the user launches live tv while playing something
            if (mediaType != Microsoft.MediaCenter.Extensibility.MediaType.TV)
            {
                Logger.ReportVerbose("Turning off NPV");
                Application.CurrentInstance.ShowNowPlaying = false;

                if (mediaType == Microsoft.MediaCenter.Extensibility.MediaType.Audio || mediaType == Microsoft.MediaCenter.Extensibility.MediaType.DVD)
                {
                    PlaybackControllerHelper.ReturnToApplication(true);
                }
            }
            else
            {
                Logger.ReportVerbose("Not turning off NPV because Live TV is playing.");
            }

            Helper.AllowSleep();

            // Fire the OnFinished event for each item
            Async.Queue(Async.ThreadPoolName.PlaybackFinished, () => OnPlaybackFinished(e));
        }
示例#17
0
        private void SkipTimerExpired(object sender, EventArgs args)
        {
            Application.UIDeferredInvokeIfRequired(() => {
                if (SkipAmount != 0)
                {
                    lock (SkipTimer)
                    {
                        if (SkipAmount != 0)
                        {
                            Logger.ReportVerbose("================ Skipping {0} seconds", SkipAmount);
                            Application.CurrentInstance.RecentUserInput = true;
                            var current  = Application.MediaExperience.Transport.Position.Ticks;
                            var duration = CurrentFileDurationTicks > 0 ? CurrentFileDurationTicks : PlaybackControllerHelper.GetDurationOfCurrentlyPlayingMedia(Application.MediaExperience.MediaMetadata);
                            if (duration == 0)
                            {
                                // last ditch get from our metadata
                                var playable = GetCurrentPlayableItem();
                                duration     = playable != null ? playable.CurrentMedia.RuntimeTicks : long.MaxValue;
                            }

                            var pos = SkipAmount > 0 ? Math.Min(current + TimeSpan.FromSeconds(SkipAmount).Ticks, duration)
                                      : Math.Max(current - TimeSpan.FromSeconds(-SkipAmount).Ticks, 0);
                            SkipAmount = 0;
                            Seek(pos);
                        }
                    }
                }
            });
        }
示例#18
0
 /// <summary>
 /// Stops playback
 /// </summary>
 protected override void StopInternal()
 {
     PlaybackControllerHelper.Stop();
 }
示例#19
0
        private void HandlePropertyChange(MediaCenterEnvironment env, MediaExperience exp, MediaTransport transport, string property)
        {
            PlayState state;
            long      positionTicks = 0;

            // If another application is playing the content, such as the WMC autoplay handler, we will
            // not have permission to access Transport properties
            // But we can look at MediaExperience.MediaType to determine if something is playing
            try
            {
                state         = transport.PlayState;
                positionTicks = transport.Position.Ticks;
            }
            catch (InvalidOperationException)
            {
                Logger.ReportVerbose("HandlePropertyChange was not able to access MediaTransport. Defaulting values.");
                state = exp.MediaType == Microsoft.MediaCenter.Extensibility.MediaType.Unknown ? Microsoft.MediaCenter.PlayState.Undefined : Microsoft.MediaCenter.PlayState.Playing;
            }

            bool playstateChanged = state != _CurrentPlayState;

            _CurrentPlayState = state;

            // Determine if playback has stopped. Per MSDN documentation, Finished is no longer used with Windows 7
            bool isStopped = state == Microsoft.MediaCenter.PlayState.Finished || state == Microsoft.MediaCenter.PlayState.Stopped || state == Microsoft.MediaCenter.PlayState.Undefined;

            // Don't get tripped up at the initial state of Stopped with position 0
            if (!_HasStartedPlaying)
            {
                if (!isStopped)
                {
                    Logger.ReportVerbose("HandlePropertyChange has recognized that playback has started");
                    _HasStartedPlaying = true;
                    IsStreaming        = Playable.CurrentFile.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
                                         Playable.CurrentFile.StartsWith("https://", StringComparison.OrdinalIgnoreCase);
                    if (Playable.HasMediaItems)
                    {
                        Application.CurrentInstance.CurrentlyPlayingItemId = lastItemId = Playable.CurrentMedia.Id;
                        Application.CurrentInstance.ReportPlaybackStart(Playable.CurrentMedia.ApiId, IsStreaming);
                    }
                }
                else
                {
                    return;
                }
            }

            // protect against really agressive calls
            if (property == "Position")
            {
                Application.CurrentInstance.CurrentlyPlayingItem.CurrentPlaybackPosition = positionTicks;
                var diff = (DateTime.Now - _LastTransportUpdateTime).TotalMilliseconds;

                // Only cancel out Position reports
                if (diff < 5000 && diff >= 0)
                {
                    return;
                }
            }

            _LastTransportUpdateTime = DateTime.Now;

            // Get metadata from player
            MediaMetadata metadata = exp.MediaMetadata;

            string metadataTitle    = PlaybackControllerHelper.GetTitleOfCurrentlyPlayingMedia(metadata);
            long   metadataDuration = PlaybackControllerHelper.GetDurationOfCurrentlyPlayingMedia(metadata);

            PlaybackStateEventArgs eventArgs = GetCurrentPlaybackState(metadataTitle, metadataDuration, positionTicks);

            // Only fire the progress handler while playback is still active, because once playback stops position will be reset to 0
            OnProgress(eventArgs);

            if (eventArgs.Item != null && eventArgs.Item.HasMediaItems && eventArgs.Item.CurrentMedia.Id != lastItemId)
            {
                // started playing a new item - update
                Application.CurrentInstance.CurrentlyPlayingItemId = lastItemId = eventArgs.Item.MediaItems.ElementAt(eventArgs.CurrentMediaIndex).Id;
            }


            Application.CurrentInstance.ShowNowPlaying = eventArgs.Item == null || eventArgs.Item.ShowNowPlayingView;

            if (playstateChanged)
            {
                FirePropertyChanged("IsPaused");

                if (state == Microsoft.MediaCenter.PlayState.Paused)
                {
                    // allow screensavers/sleep
                    Helper.AllowSleep();
                }
                else if (state == Microsoft.MediaCenter.PlayState.Playing || state == Microsoft.MediaCenter.PlayState.Buffering)
                {
                    // disallow again
                    Helper.PreventSleep();
                }

                // Get the title from the PlayableItem, if it's available. Otherwise use MediaMetadata
                string title = eventArgs.Item == null ? metadataTitle : (eventArgs.Item.HasMediaItems ? eventArgs.Item.MediaItems.ElementAt(eventArgs.CurrentMediaIndex).Name : eventArgs.Item.Files.ElementAt(eventArgs.CurrentFileIndex));

                Logger.ReportVerbose("Playstate changed to {0} for {1}, PositionTicks:{2}, Playlist Index:{3}", state, title, positionTicks, eventArgs.CurrentFileIndex);
                //Logger.ReportVerbose("Refresh rate is {0}", DisplayUtil.GetCurrentRefreshRate());

                PlayStateChanged();
                Logger.ReportVerbose("Back from PlayStateChanged");
            }

            if (isStopped)
            {
                Logger.ReportVerbose("Calling HandleStopedState");
                HandleStoppedState(env, exp, transport, eventArgs);
            }
        }
        private void PlayInternal(BaseItem item)
        {
            if (!item.ThemesLoaded)
            {
                item.LoadThemes();
            }

            var coll = new MediaCollection();

            if (item.ThemeVideos != null && item.ThemeVideos.Count > 0)
            {
                for (var i = 0; i < Config.Instance.ThemeBackgroundRepeat; i++)
                {
                    item.ThemeVideos.ForEach(v => coll.AddItem(v.Path));
                }

                IsPlayingVideo = true;
            }

            else if (item.ThemeSongs != null && item.ThemeSongs.Count > 0)
            {
                for (var i = 0; i < Config.Instance.ThemeBackgroundRepeat; i++)
                {
                    item.ThemeSongs.ForEach(a => coll.AddItem(a.Path));
                }

                IsPlayingVideo = false;
            }
            else if (Config.Instance.PlayTrailerAsBackground)
            {
                var movie = item as Movie;
                if (movie != null && movie.TrailerFiles.Any())
                {
                    for (var i = 0; i < Config.Instance.ThemeBackgroundRepeat; i++)
                    {
                        foreach (var trailerFile in movie.TrailerFiles)
                        {
                            coll.AddItem(trailerFile);
                        }
                    }

                    IsPlayingVideo = true;
                }
            }

            if (coll.Any())
            {
                Application.UIDeferredInvokeIfRequired(() =>
                {
                    //stop anything currently playing
                    PlaybackControllerHelper.Stop();

                    var mce              = Application.MediaCenterEnvironment;
                    mce.PropertyChanged += EnvironmentPropertyChange;

                    if (mce.PlayMedia(MediaType.MediaCollection, coll, false))
                    {
                        IsPlaying = true;
                        Application.CurrentInstance.ShowNowPlaying = IsPlayingVideo;
                        CurrentScope = item;
                    }
                    else
                    {
                        mce.PropertyChanged -= EnvironmentPropertyChange;
                    }
                });
            }
        }
        /// <summary>
        /// Plays or queues Media
        /// </summary>
        protected virtual void PlayPlayableItem(PlayableItem playable)
        {
            this.Playable      = playable;
            _HasStartedPlaying = false;

            // Get this now since we'll be using it frequently
            MediaCenterEnvironment mediaCenterEnvironment = AddInHost.Current.MediaCenterEnvironment;

            try
            {
                // Attach event handler to MediaCenterEnvironment
                // We need this because if you press stop on a dvd menu without ever playing, Transport.PropertyChanged will never fire
                mediaCenterEnvironment.PropertyChanged -= MediaCenterEnvironment_PropertyChanged;
                mediaCenterEnvironment.PropertyChanged += MediaCenterEnvironment_PropertyChanged;

                if (!CallPlayMediaForPlayableItem(mediaCenterEnvironment, playable))
                {
                    mediaCenterEnvironment.PropertyChanged -= MediaCenterEnvironment_PropertyChanged;

                    OnErrorPlayingItem(playable, "PlayMedia returned false");
                    return;
                }

                MediaExperience exp = mediaCenterEnvironment.MediaExperience ?? PlaybackControllerHelper.GetMediaExperienceUsingReflection();

                if (exp != null)
                {
                    MediaTransport transport = exp.Transport;

                    if (transport != null)
                    {
                        transport.PropertyChanged -= MediaTransport_PropertyChanged;
                        transport.PropertyChanged += MediaTransport_PropertyChanged;

                        // If using the legacy api we have to resume manually
                        if (_CurrentMediaCollection == null)
                        {
                            long startPosition = playable.StartPositionTicks;

                            if (startPosition > 0)
                            {
                                TimeSpan startPos = TimeSpan.FromTicks(startPosition);

                                Logger.ReportVerbose("Seeking to " + startPos.ToString());

                                transport.Position = startPos;
                            }
                        }
                    }
                    else
                    {
                        Logger.ReportWarning("PlayPlayableItem: MediaTransport is null");
                    }

                    if (playable.GoFullScreen)
                    {
                        Logger.ReportVerbose("Going fullscreen");
                        exp.GoToFullScreen();
                    }
                }
                else
                {
                    Logger.ReportWarning("PlayPlayableItem: MediaExperience is null");
                }
            }
            catch (Exception ex)
            {
                OnErrorPlayingItem(playable, ex);
            }
        }