public static bool UseLegacyApi(PlayableItem item)
        {
            // Extenders don't support MediaCollections
            if (Application.RunningOnExtender)
            {
                return true;
            }

            int numFiles = item.FilesFormattedForPlayer.Count();

            // Use the old api when there is just one file in order to avoid the annoying ding sound after playback.
            if (numFiles == 1)
            {
                return true;
            }

            // MediaCollections have performance issues with a large number of items
            if (numFiles > 200)
            {
                return true;
            }

            if (item.HasVideo)
            {
                return false;
            }

            // No videos found, use the legacy api
            return true;
        }
Example #2
0
        public static bool UseLegacyApi(PlayableItem item)
        {
            // Extenders don't support MediaCollections
            if (Application.RunningOnExtender)
            {
                return(true);
            }

            int numFiles = item.FilesFormattedForPlayer.Count();

            // Use the old api when there is just one file in order to avoid the annoying ding sound after playback.
            if (numFiles == 1)
            {
                return(true);
            }

            // MediaCollections have performance issues with a large number of items
            if (numFiles > 200)
            {
                return(true);
            }

            if (item.HasVideo)
            {
                return(false);
            }

            // No videos found, use the legacy api
            return(true);
        }
Example #3
0
        public static Microsoft.MediaCenter.MediaType GetMediaType(PlayableItem playable)
        {
            if (playable.HasVideo)
            {
                return(Microsoft.MediaCenter.MediaType.Video);
            }

            return(Microsoft.MediaCenter.MediaType.Audio);
        }
        /// <summary>
        /// Then playback is based on Media items, this will populate the MediaCollection using the items
        /// </summary>
        public static void PopulateMediaCollectionUsingMediaItems(PlaybackController controllerInstance, MediaCollection coll, PlayableItem playable)
        {
            int currentFileIndex = 0;
            int collectionIndex = coll.Count;
            int numItems = playable.MediaItems.Count();

            for (int mediaIndex = 0; mediaIndex < numItems; mediaIndex++)
            {
                Media media = playable.MediaItems.ElementAt(mediaIndex);

                IEnumerable<string> files = controllerInstance.GetPlayableFiles(media);

                int numFiles = files.Count();

                // Create a MediaCollectionItem for each file to play
                for (int i = 0; i < numFiles; i++)
                {
                    string path = files.ElementAt(i);

                    Dictionary<string, object> friendlyData = new Dictionary<string, object>();

                    // Embed the playlist index, since we could have multiple playlists queued up
                    // which prevents us from being able to use MediaCollection.CurrentIndex
                    friendlyData["FilePlaylistPosition"] = currentFileIndex.ToString();

                    // Embed the PlayableItemId so we can identify which one to track progress for
                    friendlyData["PlayableItemId"] = playable.Id.ToString();

                    // Embed the Media index so we can identify which one to track progress for
                    friendlyData["MediaIndex"] = mediaIndex.ToString();

                    // Set a friendly title
                    friendlyData["Title"] = media.Name;

                    coll.AddItem(path, collectionIndex, -1, string.Empty, friendlyData);

                    currentFileIndex++;
                    collectionIndex++;
                }
            }
        }
Example #5
0
        /// <summary>
        /// When playback is based purely on file paths, this will populate the MediaCollection using the paths
        /// </summary>
        public static void PopulateMediaCollectionUsingFiles(MediaCollection coll, PlayableItem playable, int startIndex, int count)
        {
            int    numFiles = playable.Files.Count();
            string idString = playable.Id.ToString();

            // Create a MediaCollectionItem for each file to play
            for (int i = startIndex; i < count; i++)
            {
                string path = playable.Files.ElementAt(i);

                Dictionary <string, object> friendlyData = new Dictionary <string, object>();

                // Embed the playlist index, since we could have multiple playlists queued up
                // which prevents us from being able to use MediaCollection.CurrentIndex
                friendlyData["FilePlaylistPosition"] = i.ToString();

                // Embed the PlayableItemId so we can identify which one to track progress for
                friendlyData["PlayableItemId"] = idString;

                coll.AddItem(path, i, -1, string.Empty, friendlyData);
            }
        }
 public static bool RequiresWPL(PlayableItem playable)
 {
     return playable.FilesFormattedForPlayer.Count() > 1 && playable.HasVideo;
 }
        /// <summary>
        /// When playback is based purely on file paths, this will populate the MediaCollection using the paths
        /// </summary>
        public static void PopulateMediaCollectionUsingFiles(MediaCollection coll, PlayableItem playable, int startIndex, int count)
        {
            int numFiles = playable.Files.Count();
            string idString = playable.Id.ToString();

            // Create a MediaCollectionItem for each file to play
            for (int i = startIndex; i < count; i++)
            {
                string path = playable.Files.ElementAt(i);

                Dictionary<string, object> friendlyData = new Dictionary<string, object>();

                // Embed the playlist index, since we could have multiple playlists queued up
                // which prevents us from being able to use MediaCollection.CurrentIndex
                friendlyData["FilePlaylistPosition"] = i.ToString();

                // Embed the PlayableItemId so we can identify which one to track progress for
                friendlyData["PlayableItemId"] = idString;

                coll.AddItem(path, i, -1, string.Empty, friendlyData);
            }
        }
 /// <summary>
 /// When playback is based purely on file paths, this will populate the MediaCollection using the paths
 /// </summary>
 public static void PopulateMediaCollectionUsingFiles(MediaCollection coll, PlayableItem playable)
 {
     PopulateMediaCollectionUsingFiles(coll, playable, 0, playable.Files.Count());
 }
        public static Microsoft.MediaCenter.MediaType GetMediaType(PlayableItem playable)
        {
            if (playable.HasVideo)
            {
                return Microsoft.MediaCenter.MediaType.Video;
            }

            return Microsoft.MediaCenter.MediaType.Audio;
        }
        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");
            }
        }
Example #11
0
        /// <summary>
        /// Then playback is based on Media items, this will populate the MediaCollection using the items
        /// </summary>
        public static void PopulateMediaCollectionUsingMediaItems(PlaybackController controllerInstance, MediaCollection coll, PlayableItem playable)
        {
            int currentFileIndex = 0;
            int collectionIndex  = coll.Count;
            int numItems         = playable.MediaItems.Count();

            for (int mediaIndex = 0; mediaIndex < numItems; mediaIndex++)
            {
                Media media = playable.MediaItems.ElementAt(mediaIndex);

                IEnumerable <string> files = controllerInstance.GetPlayableFiles(media);

                int numFiles = files.Count();

                // Create a MediaCollectionItem for each file to play
                for (int i = 0; i < numFiles; i++)
                {
                    string path = files.ElementAt(i);

                    Dictionary <string, object> friendlyData = new Dictionary <string, object>();

                    // Embed the playlist index, since we could have multiple playlists queued up
                    // which prevents us from being able to use MediaCollection.CurrentIndex
                    friendlyData["FilePlaylistPosition"] = currentFileIndex.ToString();

                    // Embed the PlayableItemId so we can identify which one to track progress for
                    friendlyData["PlayableItemId"] = playable.Id.ToString();

                    // Embed the Media index so we can identify which one to track progress for
                    friendlyData["MediaIndex"] = mediaIndex.ToString();

                    // Set a friendly title
                    friendlyData["Title"] = media.Name;

                    var song = media as Song;

                    if (song != null)
                    {
                        var itemImage = song.PrimaryImagePath;

                        // The following "friendly" data fields are undocumented but working for song items...
                        if (playable.Folder != null)
                        {
                            // This is either a music album or a playlist
                            friendlyData["AlbumTitle"] = playable.Folder.Name;
                            if (string.IsNullOrEmpty(itemImage))
                            {
                                itemImage = playable.Folder.PrimaryImagePath;
                            }
                        }
                        else
                        {
                            friendlyData["AlbumTitle"] = song.Album;
                        }

                        friendlyData["AlbumArtist"] = song.AlbumArtist;
                        friendlyData["Artist"]      = song.Artist;
                        friendlyData["TrackNumber"] = currentFileIndex;

                        if (song.PremierDate != DateTime.MinValue)
                        {
                            friendlyData["YearReleased"] = song.PremierDate.Year;
                        }

                        if (!string.IsNullOrEmpty(itemImage))
                        {
                            friendlyData["AlbumCoverUrl"] = itemImage;
                        }
                    }

                    coll.AddItem(path, collectionIndex, -1, string.Empty, friendlyData);

                    currentFileIndex++;
                    collectionIndex++;
                }
            }
        }
        /// <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;
        }
 /// <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);
     }
 }
 protected virtual void QueuePlayableItem(PlayableItem playable)
 {
     if (_CurrentMediaCollection == null)
     {
         QueuePlayableItemLegacy(playable);
     }
     else
     {
         QueuePlayableItemIntoMediaCollection(playable);
     }
 }
        /// <summary>
        /// Plays or queues Media
        /// </summary>
        protected virtual void PlayPlayableItem(PlayableItem 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);
            }
        }
 /// <summary>
 /// Plays Media
 /// </summary>
 protected override void PlayMediaInternal(PlayableItem playable)
 {
     if (playable.QueueItem)
     {
         Microsoft.MediaCenter.UI.Application.DeferredInvoke(_ => QueuePlayableItem(playable));
     }
     else
     {
         Microsoft.MediaCenter.UI.Application.DeferredInvoke(_ => PlayPlayableItem(playable));
     }
 }
Example #17
0
        /// <summary>
        /// Then playback is based on Media items, this will populate the MediaCollection using the items
        /// </summary>
        public static void PopulateMediaCollectionUsingMediaItems(PlaybackController controllerInstance, MediaCollection coll, PlayableItem playable)
        {
            int currentFileIndex = 0;
            int collectionIndex  = coll.Count;
            int numItems         = playable.MediaItems.Count();

            for (int mediaIndex = 0; mediaIndex < numItems; mediaIndex++)
            {
                Media media = playable.MediaItems.ElementAt(mediaIndex);

                IEnumerable <string> files = controllerInstance.GetPlayableFiles(media);

                int numFiles = files.Count();

                // Create a MediaCollectionItem for each file to play
                for (int i = 0; i < numFiles; i++)
                {
                    string path = files.ElementAt(i);

                    Dictionary <string, object> friendlyData = new Dictionary <string, object>();

                    // Embed the playlist index, since we could have multiple playlists queued up
                    // which prevents us from being able to use MediaCollection.CurrentIndex
                    friendlyData["FilePlaylistPosition"] = currentFileIndex.ToString();

                    // Embed the PlayableItemId so we can identify which one to track progress for
                    friendlyData["PlayableItemId"] = playable.Id.ToString();

                    // Embed the Media index so we can identify which one to track progress for
                    friendlyData["MediaIndex"] = mediaIndex.ToString();

                    // Set a friendly title
                    friendlyData["Title"] = media.Name;

                    coll.AddItem(path, collectionIndex, -1, string.Empty, friendlyData);

                    currentFileIndex++;
                    collectionIndex++;
                }
            }
        }
Example #18
0
 public static bool RequiresWPL(PlayableItem playable)
 {
     return(playable.FilesFormattedForPlayer.Count() > 1 && playable.HasVideo);
 }
Example #19
0
 /// <summary>
 /// When playback is based purely on file paths, this will populate the MediaCollection using the paths
 /// </summary>
 public static void PopulateMediaCollectionUsingFiles(MediaCollection coll, PlayableItem playable)
 {
     PopulateMediaCollectionUsingFiles(coll, playable, 0, playable.Files.Count());
 }
        public static string CreateASXPlaylist(PlayableItem playable)
        {
            // we need to filter out all invalid chars 
            var name = new string(playable.Id.ToString()
                .ToCharArray()
                .Where(e => !Path.GetInvalidFileNameChars().Contains(e))
                .ToArray());

            var playListFile = Path.Combine(ApplicationPaths.AutoPlaylistPath, name + ".asx");

            BaseItem primaryItem = playable.Folder;

            if (primaryItem == null)
            {
                primaryItem = playable.MediaItems.First();
            }

            StringWriter writer = new StringWriter();
            XmlTextWriter xml = new XmlTextWriter(writer);

            xml.Indentation = 2;
            xml.IndentChar = ' ';

            xml.WriteStartElement("ASX");
            xml.WriteAttributeString("version", "3.0");

            xml.WriteStartElement("TITLE");
            xml.WriteString(primaryItem.Name);
            xml.WriteEndElement();

            foreach (var mediaItem in playable.MediaItems)
            {
                foreach (string file in mediaItem.Files)
                {
                    xml.WriteStartElement("ENTRY");

                    xml.WriteStartElement("TITLE");
                    xml.WriteString(mediaItem.Name);
                    xml.WriteEndElement();

                    if (!string.IsNullOrEmpty(mediaItem.PrimaryImagePath))
                    {
                        xml.WriteStartElement("PARAM");
                        xml.WriteAttributeString("name", "WM/AlbumCoverURL");
                        xml.WriteAttributeString("value", mediaItem.PrimaryImagePath);
                        xml.WriteEndElement();
                    }

                    if (!string.IsNullOrEmpty(mediaItem.Overview))
                    {
                        xml.WriteStartElement("PARAM");
                        xml.WriteAttributeString("name", "Description");
                        xml.WriteAttributeString("value", mediaItem.Overview);
                        xml.WriteEndElement();
                    }

                    var song = mediaItem as Song;

                    if (song != null)
                    {
                        xml.WriteStartElement("PARAM");
                        xml.WriteAttributeString("name", "MediaType");
                        xml.WriteAttributeString("value", "audio");
                        xml.WriteEndElement();

                        if (song.CriticRating.HasValue)
                        {
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "UserRating");
                            xml.WriteAttributeString("value", Math.Ceiling(song.CriticRating.Value).ToString());
                            xml.WriteEndElement();
                        }

                        if (song.PremierDate != DateTime.MinValue)
                        {
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "ReleaseDateDay");
                            xml.WriteAttributeString("value", song.PremierDate.Day.ToString());
                            xml.WriteEndElement();
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "ReleaseDateMonth");
                            xml.WriteAttributeString("value", song.PremierDate.Month.ToString());
                            xml.WriteEndElement();
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "ReleaseDateYear");
                            xml.WriteAttributeString("value", song.PremierDate.Year.ToString());
                            xml.WriteEndElement();
                        }

                        if (song.RuntimeTicks > 0)
                        {
                            var ts = TimeSpan.FromTicks(song.RuntimeTicks);
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "Duration");
                            xml.WriteAttributeString("value", ts.TotalSeconds.ToString("F0"));
                            xml.WriteEndElement();
                        }

                        if (!string.IsNullOrEmpty(song.Artist))
                        {
                            xml.WriteStartElement("AUTHOR");
                            xml.WriteString(song.Artist);
                            xml.WriteEndElement();
                        }

                        if (!string.IsNullOrEmpty(song.AlbumArtist))
                        {
                            xml.WriteStartElement("WM/AlbumArtist");
                            xml.WriteString(song.AlbumArtist);
                            xml.WriteEndElement();
                        }

                        var albumName = song.Album;

                        if (string.IsNullOrEmpty(albumName) && primaryItem is Folder)
                        {
                            albumName = primaryItem.Name;
                        }

                        if (!string.IsNullOrEmpty(albumName))
                        {
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "WM/AlbumTitle");
                            xml.WriteAttributeString("value", albumName);
                            xml.WriteEndElement();
                        }

                        if (song.Genres != null)
                        {
                            foreach (var genre in song.Genres)
                            {
                                xml.WriteStartElement("PARAM");
                                xml.WriteAttributeString("name", "WM/Genre");
                                xml.WriteAttributeString("value", genre);
                                xml.WriteEndElement();
                            }
                        }
                    }

                    xml.WriteStartElement("REF");
                    xml.WriteAttributeString("href", file);
                    xml.WriteEndElement();

                    xml.WriteEndElement();
                }
            }

            xml.WriteEndElement();

            File.WriteAllText(playListFile, writer.ToString());

            return playListFile;
        }
        private bool CallPlayMediaUsingMediaCollection(MediaCenterEnvironment mediaCenterEnvironment, PlayableItem playable)
        {
            MediaCollection 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;
        }
Example #22
0
        public static string CreateASXPlaylist(PlayableItem playable)
        {
            // we need to filter out all invalid chars
            var name = new string(playable.Id.ToString()
                                  .ToCharArray()
                                  .Where(e => !Path.GetInvalidFileNameChars().Contains(e))
                                  .ToArray());

            var playListFile = Path.Combine(ApplicationPaths.AutoPlaylistPath, name + ".asx");

            BaseItem primaryItem = playable.Folder;

            if (primaryItem == null)
            {
                primaryItem = playable.MediaItems.First();
            }

            StringWriter  writer = new StringWriter();
            XmlTextWriter xml    = new XmlTextWriter(writer);

            xml.Indentation = 2;
            xml.IndentChar  = ' ';

            xml.WriteStartElement("ASX");
            xml.WriteAttributeString("version", "3.0");

            xml.WriteStartElement("TITLE");
            xml.WriteString(primaryItem.Name);
            xml.WriteEndElement();

            foreach (var mediaItem in playable.MediaItems)
            {
                foreach (string file in mediaItem.Files)
                {
                    xml.WriteStartElement("ENTRY");

                    xml.WriteStartElement("TITLE");
                    xml.WriteString(mediaItem.Name);
                    xml.WriteEndElement();

                    if (!string.IsNullOrEmpty(mediaItem.PrimaryImagePath))
                    {
                        xml.WriteStartElement("PARAM");
                        xml.WriteAttributeString("name", "WM/AlbumCoverURL");
                        xml.WriteAttributeString("value", mediaItem.PrimaryImagePath);
                        xml.WriteEndElement();
                    }

                    if (!string.IsNullOrEmpty(mediaItem.Overview))
                    {
                        xml.WriteStartElement("PARAM");
                        xml.WriteAttributeString("name", "Description");
                        xml.WriteAttributeString("value", mediaItem.Overview);
                        xml.WriteEndElement();
                    }

                    var song = mediaItem as Song;

                    if (song != null)
                    {
                        xml.WriteStartElement("PARAM");
                        xml.WriteAttributeString("name", "MediaType");
                        xml.WriteAttributeString("value", "audio");
                        xml.WriteEndElement();

                        if (song.CriticRating.HasValue)
                        {
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "UserRating");
                            xml.WriteAttributeString("value", Math.Ceiling(song.CriticRating.Value).ToString());
                            xml.WriteEndElement();
                        }

                        if (song.PremierDate != DateTime.MinValue)
                        {
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "ReleaseDateDay");
                            xml.WriteAttributeString("value", song.PremierDate.Day.ToString());
                            xml.WriteEndElement();
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "ReleaseDateMonth");
                            xml.WriteAttributeString("value", song.PremierDate.Month.ToString());
                            xml.WriteEndElement();
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "ReleaseDateYear");
                            xml.WriteAttributeString("value", song.PremierDate.Year.ToString());
                            xml.WriteEndElement();
                        }

                        if (song.RuntimeTicks > 0)
                        {
                            var ts = TimeSpan.FromTicks(song.RuntimeTicks);
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "Duration");
                            xml.WriteAttributeString("value", ts.TotalSeconds.ToString("F0"));
                            xml.WriteEndElement();
                        }

                        if (!string.IsNullOrEmpty(song.Artist))
                        {
                            xml.WriteStartElement("AUTHOR");
                            xml.WriteString(song.Artist);
                            xml.WriteEndElement();
                        }

                        if (!string.IsNullOrEmpty(song.AlbumArtist))
                        {
                            xml.WriteStartElement("WM/AlbumArtist");
                            xml.WriteString(song.AlbumArtist);
                            xml.WriteEndElement();
                        }

                        var albumName = song.Album;

                        if (string.IsNullOrEmpty(albumName) && primaryItem is Folder)
                        {
                            albumName = primaryItem.Name;
                        }

                        if (!string.IsNullOrEmpty(albumName))
                        {
                            xml.WriteStartElement("PARAM");
                            xml.WriteAttributeString("name", "WM/AlbumTitle");
                            xml.WriteAttributeString("value", albumName);
                            xml.WriteEndElement();
                        }

                        if (song.Genres != null)
                        {
                            foreach (var genre in song.Genres)
                            {
                                xml.WriteStartElement("PARAM");
                                xml.WriteAttributeString("name", "WM/Genre");
                                xml.WriteAttributeString("value", genre);
                                xml.WriteEndElement();
                            }
                        }
                    }

                    xml.WriteStartElement("REF");
                    xml.WriteAttributeString("href", file);
                    xml.WriteEndElement();

                    xml.WriteEndElement();
                }
            }

            xml.WriteEndElement();

            File.WriteAllText(playListFile, writer.ToString());

            return(playListFile);
        }
 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);
     }
 }
        /// <summary>
        /// Then playback is based on Media items, this will populate the MediaCollection using the items
        /// </summary>
        public static void PopulateMediaCollectionUsingMediaItems(PlaybackController controllerInstance, MediaCollection coll, PlayableItem playable)
        {
            int currentFileIndex = 0;
            int collectionIndex = coll.Count;
            int numItems = playable.MediaItems.Count();

            for (int mediaIndex = 0; mediaIndex < numItems; mediaIndex++)
            {
                Media media = playable.MediaItems.ElementAt(mediaIndex);

                IEnumerable<string> files = controllerInstance.GetPlayableFiles(media);

                int numFiles = files.Count();

                // Create a MediaCollectionItem for each file to play
                for (int i = 0; i < numFiles; i++)
                {
                    string path = files.ElementAt(i);

                    Dictionary<string, object> friendlyData = new Dictionary<string, object>();

                    // Embed the playlist index, since we could have multiple playlists queued up
                    // which prevents us from being able to use MediaCollection.CurrentIndex
                    friendlyData["FilePlaylistPosition"] = currentFileIndex.ToString();

                    // Embed the PlayableItemId so we can identify which one to track progress for
                    friendlyData["PlayableItemId"] = playable.Id.ToString();

                    // Embed the Media index so we can identify which one to track progress for
                    friendlyData["MediaIndex"] = mediaIndex.ToString();

                    // Set a friendly title
                    friendlyData["Title"] = media.Name;

                    var song = media as Song;

                    if (song != null)
                    {
                        var itemImage = song.PrimaryImagePath;

                        // The following "friendly" data fields are undocumented but working for song items...
                        if (playable.Folder != null)
                        {
                            // This is either a music album or a playlist
                            friendlyData["AlbumTitle"] = playable.Folder.Name;
                            if (string.IsNullOrEmpty(itemImage))
                            {
                                itemImage = playable.Folder.PrimaryImagePath;
                            }
                        }
                        else
                        {
                            friendlyData["AlbumTitle"] = song.Album;
                        }

                        friendlyData["AlbumArtist"] = song.AlbumArtist;
                        friendlyData["Artist"] = song.Artist;
                        friendlyData["TrackNumber"] = currentFileIndex;

                        if (song.PremierDate != DateTime.MinValue)
                        {
                            friendlyData["YearReleased"] = song.PremierDate.Year;
                        }

                        if (!string.IsNullOrEmpty(itemImage))
                        {
                            friendlyData["AlbumCoverUrl"] = itemImage;
                        }
                    }

                    coll.AddItem(path, collectionIndex, -1, string.Empty, friendlyData);
                    
                    currentFileIndex++;
                    collectionIndex++;
                }
            }
        }