예제 #1
0
        /// <summary>
        /// Parses the XML property list.
        /// </summary>
        /// <param name="dict">A PList in which the parsed elements will be output.</param>
        /// <param name="elements">A collection of the elements in the property list.</param>
        internal void Parse(PList dict, IEnumerable <XElement> elements)
        {
            Contract.Requires(dict != null);
            Contract.Requires(elements != null);

            for (int i = 0; i < elements.Count(); i += 2)
            {
                XElement key = elements.ElementAt(i);
                XElement val = elements.ElementAt(i + 1);

                dict[key.Value] = ParseValue(val);
            }
        }
예제 #2
0
        /// <summary>
        /// Parses an element in the XML property list.
        /// </summary>
        /// <param name="val">The XML element to parse.</param>
        /// <returns>The converted object representation of the element.</returns>
        private object ParseValue(XElement val)
        {
            Contract.Requires(val != null);

            switch (val.Name.ToString())
            {
            case "string":
                return(val.Value);

            case "integer":
                return(long.Parse(val.Value));

            case "real":
                return(float.Parse(val.Value));

            case "true":
                return(true);

            case "false":
                return(false);

            case "dict":
                PList plist = new PList();
                Parse(plist, val.Elements());
                return(plist);

            case "array":
                List <object> list = ParseArray(val.Elements());
                return(list);

            case "date":
                return(DateTime.Parse(val.Value));

            case "data":
                return(Convert.FromBase64String(val.Value));

            default:
                throw new ArgumentException("Unsupported");
            }
        }
예제 #3
0
        /// <summary>
        /// Loads the iTunes Library from an XML file and reads the PLIST-formatted contents.
        /// </summary>
        /// <param name="library">The folder containing the iTunes Library.</param>
        /// <returns>Whether the XML file exists or not.</returns>
        /// <returns>Whether the process was successful or not.</returns>
        private static async Task <bool> LoadLibraryFromXml(StorageFolder library)
        {
            try
            {
                StorageFile xmlFile = await library.GetFileAsync(ITUNES_XML);

                XDocument xmlDocument = null;

                // Attempt to read the XML file format
                var xmlStreamInfo = await xmlFile.TryReadAsync();

                OperatingSystem libraryType = xmlStreamInfo.Item1.Value;

                using (var xmlStream = xmlStreamInfo.Item2)
                {
                    xmlDocument = XDocument.Load(xmlStream.AsStreamForRead());
                }

                // Get the PLIST from the XML and parse
                var plist = new PList(xmlDocument);

                IEnumerable <Album>    libraryAlbums;
                IEnumerable <Playlist> libraryPlaylists;
                ParseXml(library.Path, plist, out libraryAlbums, out libraryPlaylists);

                // Save the parsed objects if possible
                TunesDataSource.Default = new TunesDataSource(libraryAlbums, libraryPlaylists, libraryType);
                await SerializeAsync();

                return(true);
            }
            catch (Exception)
            {
                return(false);
            }
        }
예제 #4
0
        /// <summary>
        /// Helper method to process an iTunes PLIST into a List of Album objects.
        /// </summary>
        /// <returns>Whether the process was successful or not.</returns>
        /// <exception cref="System.Exception">if the PLIST parsing failed.</exception>
        private static void ParseXml(string actualLibaryPath, PList libraryIndex, out IEnumerable <Album> outAlbums, out IEnumerable <Playlist> outPlaylists)
        {
            Contract.Requires(!string.IsNullOrEmpty(actualLibaryPath));
            Contract.Requires(libraryIndex != null);

            // file://localhost/C:/Users/Steve/Music/iTunes/iTunes%20Media/
            // file://localhost/Users/Steve/Music/iTunes/iTunes%20Media/

            string musicFolderString = libraryIndex.GetStringOrDefault("Music Folder");
            string declaredMediaPath = new Uri(musicFolderString).LocalPath;
            var    absoluteMediaPath = GetAbsoluteMediaPathUri(actualLibaryPath, declaredMediaPath);

            IEnumerable <PList> trackListRaw    = libraryIndex.GetOrDefault <PList>("Tracks").Values.Cast <PList>();
            IEnumerable <PList> playlistListRaw = libraryIndex.GetOrDefault <List <object> >("Playlists").Cast <PList>();

            if (string.IsNullOrEmpty(declaredMediaPath) || trackListRaw == null || playlistListRaw == null)
            {
                throw new InvalidOperationException();
            }

            Dictionary <AlbumKey, AlbumBuilder> albumBuilders = new Dictionary <AlbumKey, AlbumBuilder>();

            foreach (var trackInfoRaw in trackListRaw)
            {
                string trackLocationString = trackInfoRaw.GetStringOrDefault("Location");
                long   trackBitRateLong    = trackInfoRaw.GetLongOrDefault("Bit Rate");

                if (IsValidMediaKind(trackLocationString, trackBitRateLong))
                {
                    string titleString       = trackInfoRaw.GetStringOrDefault("Name");
                    string albumString       = trackInfoRaw.GetStringOrDefault("Album");
                    string artistString      = trackInfoRaw.GetStringOrDefault("Artist");
                    string albumArtistString = trackInfoRaw.GetStringOrDefault("Album Artist") ?? artistString;
                    int    trackIDInt        = trackInfoRaw.GetIntOrDefault("Track ID");
                    int    discNumberInt     = trackInfoRaw.GetIntOrDefault("Disc Number");
                    int    trackNumberInt    = trackInfoRaw.GetIntOrDefault("Track Number");
                    int    yearInt           = trackInfoRaw.GetIntOrDefault("Year");
                    int    totalTimeInt      = trackInfoRaw.GetIntOrDefault("Total Time");

                    var    relativeTrackLocation   = new Uri(trackLocationString).LocalPath.Replace(declaredMediaPath, string.Empty);
                    string formattedLocationString = Path.Combine(absoluteMediaPath, relativeTrackLocation);

                    AlbumBuilder albumBuilder;
                    var          albumBuilderID = new AlbumKey(albumString, albumArtistString);
                    if (!albumBuilders.TryGetValue(albumBuilderID, out albumBuilder))
                    {
                        albumBuilder = new AlbumBuilder(albumString, albumArtistString, yearInt);
                        albumBuilders.Add(albumBuilderID, albumBuilder);
                    }

                    Contract.Assume(albumBuilder != null);                     // New AlbumBuilder should have been created if it doesn't yet exist.

                    albumBuilder.AddTrack(
                        trackID: trackIDInt,
                        title: titleString,
                        artist: artistString,
                        discNumber: discNumberInt,
                        trackNumber: trackNumberInt,
                        location: formattedLocationString,
                        totalTime: new TimeSpan(0, 0, totalTimeInt / 1000));
                }
            }

            IEnumerable <Album> libraryAlbumsUnsorted = albumBuilders.Values.AsParallel().Select(thatBuilder => thatBuilder.GetAlbum()).ToList();
            IEnumerable <Track> libraryTracksUnsorted = libraryAlbumsUnsorted.AsParallel().SelectMany(thatAlbum => thatAlbum.TrackList);

            List <Playlist> libraryPlaylists = new List <Playlist>();

            foreach (var playlistInfoRaw in playlistListRaw)
            {
                List <object> playlistItemsRaw = playlistInfoRaw.GetOrDefault <List <object> >("Playlist Items");
                if (playlistItemsRaw != null)
                {
                    List <Track> playlistItems = playlistItemsRaw
                                                 .Cast <PList>() // This is the only thing I can think of that would cause an exception in this method.
                                                 .Select(thatPlist => thatPlist.GetIntOrDefault("Track ID"))
                                                 .Join(libraryTracksUnsorted,
                                                       itemIndex => itemIndex,
                                                       track => track.TrackID,
                                                       (index, track) => track).ToList();

                    if (playlistItems.Count > 0)
                    {
                        libraryPlaylists.Add(new Playlist(playlistInfoRaw.GetStringOrDefault("Name"), playlistItems));
                    }
                }
            }

            outAlbums    = libraryAlbumsUnsorted.OrderBy(thatAlbum => thatAlbum.AlbumArtist).ThenBy(thatAlbum => thatAlbum.Title);
            outPlaylists = libraryPlaylists.OrderBy(playlist => playlist.Title);
        }