banshee r5180 - in trunk/banshee: . src/Extensions/Banshee.AudioCd/Banshee.AudioCd src/Libraries/MusicBrainz src/Libraries/MusicBrainz/MusicBrainz



Author: gburt
Date: Thu Apr  2 20:28:54 2009
New Revision: 5180
URL: http://svn.gnome.org/viewvc/banshee?rev=5180&view=rev

Log:
2009-04-02  Gabriel Burt  <gabriel burt gmail com>

	Updated to latest MusicBrainz# courtesy of Scott Peterson and Tom Corner.

	* src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdDiscModel.cs:
	Use the new MB# API.

	* src/Libraries/MusicBrainz/*: Updated to latest from musicbrainz.org.  I
	did comment out the DiscWin32NT references in LocalDisc.

Added:
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/DiscLinux.cs
      - copied, changed from r5179, /trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/LinuxDisc.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/DiscWin32.cs
      - copied, changed from r5179, /trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Win32Disc.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/DiscWin32NT.cs
Removed:
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/LinuxDisc.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Win32Disc.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdDiscModel.cs
   trunk/banshee/src/Libraries/MusicBrainz/Makefile.am
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz.csproj
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Artist.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Disc.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Event.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Label.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/LocalDisc.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzEntity.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzException.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzItem.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzObject.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzService.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Query.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Relation.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Release.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Track.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Utils.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/XmlRequestEventArgs.cs
   trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/sync.sh

Modified: trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdDiscModel.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdDiscModel.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdDiscModel.cs	Thu Apr  2 20:28:54 2009
@@ -89,17 +89,18 @@
             if (mb_disc == null) {
                 throw new ApplicationException ("Could not read contents of the disc. Platform may not be supported.");
             }
-            
-            for (int i = 0, n = mb_disc.TrackDurations.Length; i < n; i++) {
+
+            TimeSpan[] durations = mb_disc.GetTrackDurations ();
+            for (int i = 0, n = durations.Length; i < n; i++) {
                 AudioCdTrackInfo track = new AudioCdTrackInfo (this, volume.DeviceNode, i);
                 track.TrackNumber = i + 1;
                 track.TrackCount = n;
                 track.DiscNumber = 1;
-                track.Duration = TimeSpan.FromSeconds (mb_disc.TrackDurations[i]);
+                track.Duration = durations[i];
                 track.ArtistName = Catalog.GetString ("Unknown Artist");
                 track.AlbumTitle = Catalog.GetString ("Unknown Album");
                 track.TrackTitle = String.Format (Catalog.GetString ("Track {0}"), track.TrackNumber);
-                track.FileSize = mb_disc.TrackDurations[i] * PCM_FACTOR;
+                track.FileSize = PCM_FACTOR * (uint)track.Duration.TotalSeconds;
                 Add (track);
                 
                 duration += track.Duration;
@@ -120,81 +121,81 @@
             OnMetadataQueryStarted (mb_disc);
             
             Release release = Release.Query (mb_disc).PerfectMatch ();
-            if (release == null || release.Tracks.Count != Count) {
+
+            var tracks = release.GetTracks ();
+            if (release == null || tracks.Count != Count) {
                 OnMetadataQueryFinished (false);
                 return;
             }
                         
-            disc_title = release.Title;
+            disc_title = release.GetTitle ();
             
             int disc_number = 1;
             int i = 0;
             
-            foreach (Disc disc in release.Discs) {
+            foreach (Disc disc in release.GetDiscs ()) {
                 i++;
                 if (disc.Id == mb_disc.Id) {
                     disc_number = i;
                 }
             }
             
-            DateTime release_date = DateTime.MinValue;
-            int release_event_index = -1;
-            
-            for (i = 0; i < release.Events.Count; i++) {
-                // FIXME: This is sort of lame, but from what I've seen, 
-                // the US releases generally contain more info
-                if (release.Events[i].Country == "US") {
-                    release_event_index = i;
-                    break;
+            DateTime release_date = DateTime.MaxValue;
+ 
+            foreach (Event release_event in release.GetEvents ()) {
+                if (release_event.Date != null) {
+                    try {
+                        DateTime date = DateTime.Parse (release_event.Date, ApplicationContext.InternalCultureInfo);
+                        if (date < release_date) {
+                            release_date = date;
+                        }
+                    } catch {
+                    }
                 }
             }
             
-            if (release_event_index >= 0) {
-                release_date = DateTime.Parse (release.Events[release_event_index].Date, 
-                    ApplicationContext.InternalCultureInfo);
-            }
-            
             DatabaseArtistInfo artist = new DatabaseArtistInfo ();
-            artist.Name = release.Artist.Name;
-            artist.NameSort = release.Artist.SortName;
-            artist.MusicBrainzId = release.Artist.Id;
+            var mb_artist = release.GetArtist ();
+            artist.Name = mb_artist.GetName ();
+            artist.NameSort = mb_artist.GetSortName ();
+            artist.MusicBrainzId = mb_artist.Id;
             bool is_compilation = false;
             
             DatabaseAlbumInfo album = new DatabaseAlbumInfo ();
-            album.Title = release.Title;
+            album.Title = disc_title;
             album.ArtistName = artist.Name;
             album.MusicBrainzId = release.Id;
-            album.ReleaseDate = release_date;
+            album.ReleaseDate = release_date == DateTime.MaxValue ? DateTime.MinValue : release_date;
             
             i = 0;
-
-            foreach (Track track in release.Tracks) {
+            foreach (Track track in tracks) {
                 AudioCdTrackInfo model_track = (AudioCdTrackInfo)this[i++];
+                var mb_track_artist = track.GetArtist ();
                 
                 model_track.MusicBrainzId = track.Id;
-                model_track.TrackTitle = track.Title;
-                model_track.ArtistName = track.Artist.Name;
-                model_track.AlbumTitle = release.Title;
+                model_track.TrackTitle = track.GetTitle ();
+                model_track.ArtistName = mb_track_artist.GetName ();
+                model_track.AlbumTitle = disc_title;
                 model_track.DiscNumber = disc_number;
                 model_track.Album = album;
 
                 model_track.Artist = new DatabaseArtistInfo ();
-                model_track.Artist.Name = track.Artist.Name;
-                model_track.Artist.NameSort = track.Artist.SortName;
-                model_track.Artist.MusicBrainzId = track.Artist.Id;
+                model_track.Artist.Name = model_track.ArtistName;
+                model_track.Artist.NameSort = mb_track_artist.GetSortName ();
+                model_track.Artist.MusicBrainzId = mb_track_artist.Id;
                 
-                if (!release_date.Equals (DateTime.MinValue)) {
+                if (release_date != DateTime.MinValue) {
                     model_track.Year = release_date.Year;
                 }
 
-                if (!is_compilation && track.Artist.Id != artist.MusicBrainzId) {
+                if (!is_compilation && mb_track_artist.Id != artist.MusicBrainzId) {
                     is_compilation = true;
                 }
             }
 
             if (is_compilation) {
                 album.IsCompilation = true;
-                for (i = 0; i < release.Tracks.Count; i++) {
+                for (i = 0; i < tracks.Count; i++) {
                     AudioCdTrackInfo model_track = (AudioCdTrackInfo)this[i];
                     model_track.IsCompilation = true;
                     model_track.AlbumArtist = artist.Name;

Modified: trunk/banshee/src/Libraries/MusicBrainz/Makefile.am
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/Makefile.am	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/Makefile.am	Thu Apr  2 20:28:54 2009
@@ -4,9 +4,10 @@
 SOURCES =  \
 	MusicBrainz/Artist.cs \
 	MusicBrainz/Disc.cs \
+	MusicBrainz/DiscLinux.cs \
+	MusicBrainz/DiscWin32.cs \
 	MusicBrainz/Event.cs \
 	MusicBrainz/Label.cs \
-	MusicBrainz/LinuxDisc.cs \
 	MusicBrainz/LocalDisc.cs \
 	MusicBrainz/MusicBrainzEntity.cs \
 	MusicBrainz/MusicBrainzException.cs \
@@ -18,8 +19,6 @@
 	MusicBrainz/Release.cs \
 	MusicBrainz/Track.cs \
 	MusicBrainz/Utils.cs \
-	MusicBrainz/Win32Disc.cs \
 	MusicBrainz/XmlRequestEventArgs.cs 
 
 include $(top_srcdir)/build/build.mk
-

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz.csproj
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz.csproj	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz.csproj	Thu Apr  2 20:28:54 2009
@@ -33,7 +33,6 @@
     <Compile Include="MusicBrainz\Disc.cs" />
     <Compile Include="MusicBrainz\Event.cs" />
     <Compile Include="MusicBrainz\Label.cs" />
-    <Compile Include="MusicBrainz\LinuxDisc.cs" />
     <Compile Include="MusicBrainz\LocalDisc.cs" />
     <Compile Include="MusicBrainz\MusicBrainzEntity.cs" />
     <Compile Include="MusicBrainz\MusicBrainzException.cs" />
@@ -45,8 +44,9 @@
     <Compile Include="MusicBrainz\Release.cs" />
     <Compile Include="MusicBrainz\Track.cs" />
     <Compile Include="MusicBrainz\Utils.cs" />
-    <Compile Include="MusicBrainz\Win32Disc.cs" />
     <Compile Include="MusicBrainz\XmlRequestEventArgs.cs" />
+    <Compile Include="MusicBrainz\DiscLinux.cs" />
+    <Compile Include="MusicBrainz\DiscWin32.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Artist.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Artist.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Artist.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // Artist.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -47,16 +43,12 @@
         
         #region Constructors
 
-        Artist (string mbid) : base (mbid, null)
-        {
-        }
-
-        Artist (string mbid, string parameters) : base (mbid, parameters)
+        Artist (string id) : base (id, null)
         {
         }
 
-        Artist (string mbid, ArtistReleaseType artist_release_type)
-            : this (mbid, "&inc=" + artist_release_type.ToString ())
+        Artist (string id, ArtistReleaseType artist_release_type)
+            : base (id, "&inc=" + artist_release_type.ToString ())
         {
             have_all_releases = true;
             this.artist_release_type = artist_release_type;
@@ -70,24 +62,24 @@
         
         #region Protected
         
-        protected override string UrlExtension {
+        internal override string UrlExtension {
             get { return EXTENSION; }
         }
 
-        protected override void CreateIncCore (StringBuilder builder)
+        internal override void CreateIncCore (StringBuilder builder)
         {
             AppendIncParameters (builder, artist_release_type.ToString ());
             base.CreateIncCore (builder);
         }
 
-        protected override void LoadMissingDataCore ()
+        internal override void LoadMissingDataCore ()
         {
-            Artist artist = new Artist (Id, CreateInc ());
-            type = artist.Type;
+            Artist artist = new Artist (Id);
+            type = artist.GetArtistType ();
             base.LoadMissingDataCore (artist);
         }
 
-        protected override bool ProcessAttributes (XmlReader reader)
+        internal override void ProcessAttributes (XmlReader reader)
         {
             switch (reader ["type"]) {
             case "Group":
@@ -97,44 +89,44 @@
                 type = ArtistType.Person;
                 break;
             }
-            return type != ArtistType.Unknown;
         }
 
-        protected override bool ProcessXml (XmlReader reader)
+        internal override void ProcessXmlCore (XmlReader reader)
         {
-            reader.Read ();
-            bool result = base.ProcessXml (reader);
-            if (!result) {
-                result = true;
-                switch (reader.Name) {
-                case "release-list":
-                    if (reader.ReadToDescendant ("release")) {
-                        List<Release> releases = new List<Release> ();
-                        do releases.Add (new Release (reader.ReadSubtree ()));
-                        while (reader.ReadToNextSibling ("release"));
-                        this.releases = releases.AsReadOnly ();
-                    }
-                    break;
-                default:
-                    reader.Skip (); // FIXME this is a workaround for Mono bug 334752
-                    result = false;
-                    break;
+            switch (reader.Name) {
+            case "release-list":
+                if (reader.ReadToDescendant ("release")) {
+                    List<Release> releases = new List<Release> ();
+                    do releases.Add (new Release (reader.ReadSubtree ()));
+                    while (reader.ReadToNextSibling ("release"));
+                    this.releases = releases.AsReadOnly ();
                 }
+                break;
+            default:
+                base.ProcessXmlCore (reader);
+                break;
             }
-            reader.Close ();
-            return result;
         }
         
         #endregion
 
-        #region Properties
+        #region Public
         
-        public static ArtistReleaseType DefaultArtistReleaseType =
-            new ArtistReleaseType (ReleaseStatus.Official, false);
+        static ArtistReleaseType default_artist_release_type = new ArtistReleaseType (ReleaseStatus.Official, ReleaseArtistType.SingleArtist);
+        public static ArtistReleaseType DefaultArtistReleaseType {
+            get { return default_artist_release_type; }
+            set {
+                if (value == null) throw new ArgumentNullException ("value");
+                default_artist_release_type = value;
+            }
+        }
         
         public ArtistReleaseType ArtistReleaseType {
             get { return artist_release_type; }
             set {
+                if (artist_release_type == value) {
+                    return;
+                }
                 artist_release_type = value;
                 releases = null;
                 have_all_releases = false;
@@ -147,43 +139,49 @@
         }
 
         [Queryable ("artist")]
-        public override string Name {
-            get { return base.Name; }
+        public override string GetName ()
+        {
+            return base.GetName ();
         }
 
         [Queryable ("artype")]
-        public ArtistType Type {
-            get { return GetPropertyOrDefault (ref type, ArtistType.Unknown); }
+        public ArtistType GetArtistType ()
+        {
+            return GetPropertyOrDefault (ref type, ArtistType.Unknown);
+        }
+        
+        public ReadOnlyCollection<Release> GetReleases ()
+        {
+            return releases ?? (have_all_releases
+                ? releases = new ReadOnlyCollection<Release> (new Release [0])
+                : new Artist (Id, ArtistReleaseType).GetReleases ());
         }
 
-        public ReadOnlyCollection<Release> Releases {
-            get {
-                return releases ?? (have_all_releases
-                    ? releases = new ReadOnlyCollection<Release> (new Release [0])
-                    : new Artist (Id, artist_release_type).Releases);
-            }
+        public ReadOnlyCollection<Release> GetReleases (ArtistReleaseType artistReleaseType)
+        {
+            return new Artist (Id, artistReleaseType).GetReleases ();
         }
 
         #endregion
         
         #region Static
 
-        public static Artist Get (string mbid)
+        public static Artist Get (string id)
         {
-            if (mbid == null) throw new ArgumentNullException ("mbid");
-            return new Artist (mbid);
+            if (id == null) throw new ArgumentNullException ("id");
+            return new Artist (id);
         }
 
         public static Query<Artist> Query (string name)
         {
             if (name == null) throw new ArgumentNullException ("name");
-            return new Query<Artist> (EXTENSION, QueryLimit, CreateNameParameter (name));
+            return new Query<Artist> (EXTENSION, CreateNameParameter (name));
         }
 
         public static Query<Artist> QueryLucene (string luceneQuery)
         {
             if (luceneQuery == null) throw new ArgumentNullException ("luceneQuery");
-            return new Query<Artist> (EXTENSION, QueryLimit, CreateLuceneParameter (luceneQuery));
+            return new Query<Artist> (EXTENSION, CreateLuceneParameter (luceneQuery));
         }
 
         public static implicit operator string (Artist artist)
@@ -204,37 +202,43 @@
         Person
     }
     
+    public enum ReleaseArtistType
+    {
+        VariousArtists,
+        SingleArtist
+    }
+    
     public sealed class ArtistReleaseType
     {
         string str;
 
-        public ArtistReleaseType (ReleaseType type, bool various) : this ((Enum)type, various)
+        public ArtistReleaseType (ReleaseType type, ReleaseArtistType artistType) : this ((Enum)type, artistType)
         {
         }
 
-        public ArtistReleaseType (ReleaseStatus status, bool various) : this ((Enum)status, various)
+        public ArtistReleaseType (ReleaseStatus status, ReleaseArtistType artistType) : this ((Enum)status, artistType)
         {
         }
         
-        public ArtistReleaseType (ReleaseType type, ReleaseStatus status, bool various)
+        public ArtistReleaseType (ReleaseType type, ReleaseStatus status, ReleaseArtistType artistType)
         {
             StringBuilder builder = new StringBuilder ();
-            Format (builder, type, various);
+            Format (builder, type, artistType);
             builder.Append ('+');
-            Format (builder, status, various);
+            Format (builder, status, artistType);
             str = builder.ToString ();
         }
 
-        ArtistReleaseType (Enum enumeration, bool various)
+        ArtistReleaseType (Enum enumeration, ReleaseArtistType artistType)
         {
             StringBuilder builder = new StringBuilder ();
-            Format (builder, enumeration, various);
+            Format (builder, enumeration, artistType);
             str = builder.ToString ();
         }
         
-        void Format (StringBuilder builder, Enum enumeration, bool various)
+        static void Format (StringBuilder builder, Enum enumeration, ReleaseArtistType artistType)
         {
-            builder.Append (various ? "va-" : "sa-");
+            builder.Append (artistType == ReleaseArtistType.VariousArtists ? "va-" : "sa-");
             Utils.EnumToString (builder, enumeration.ToString ());
         }
 
@@ -243,6 +247,28 @@
             return str;
         }
 
+        public override bool Equals (object o)
+        {
+            return this == o as ArtistReleaseType;
+        }
+        
+        public static bool operator ==(ArtistReleaseType artistReleaseType1, ArtistReleaseType artistReleaseType2)
+        {
+            if (Object.ReferenceEquals (artistReleaseType1, null)) {
+                return Object.ReferenceEquals (artistReleaseType2, null);
+            }
+            return !Object.ReferenceEquals (artistReleaseType2, null) && artistReleaseType1.str == artistReleaseType2.str;
+        }
+        
+        public static bool operator !=(ArtistReleaseType artistReleaseType1, ArtistReleaseType artistReleaseType2)
+        {
+            return !(artistReleaseType1 == artistReleaseType2);
+        }
+        
+        public override int GetHashCode ()
+        {
+            return str.GetHashCode ();
+        }
     }
     
     #endregion

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Disc.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Disc.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Disc.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // Disc.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Xml;
 

Copied: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/DiscLinux.cs (from r5179, /trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/LinuxDisc.cs)
==============================================================================
--- /trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/LinuxDisc.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/DiscLinux.cs	Thu Apr  2 20:28:54 2009
@@ -1,6 +1,4 @@
-#region License
-
-// LinuxDisc.cs
+// DiscLinux.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
 //
@@ -22,14 +20,12 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Runtime.InteropServices;
 
 namespace MusicBrainz
 {
-    internal sealed class LinuxDisc : LocalDisc
+    internal sealed class DiscLinux : LocalDisc
     {
         const int O_RDONLY = 0x0;
         const int O_NONBLOCK = 0x4000;
@@ -41,7 +37,7 @@
         const int CD_FRAMES = 75;
         const int XA_INTERVAL = ((60 + 90 + 2) * CD_FRAMES);
         
-        [DllImport ("libc.so.6")]
+        [DllImport ("libc.so.6", CharSet = CharSet.Auto)]
         static extern int open (string path, int flags);
         
         [DllImport ("libc.so.6")]
@@ -99,18 +95,18 @@
             
             if (ret < 0) return ret;
             
-            FirstTrack = th.cdth_trk0;
-            LastTrack = th.cdth_trk1;
+            first_track = th.cdth_trk0;
+            last_track = th.cdth_trk1;
             
             ms.addr_format = CDROM_LBA;
             ret = read_multisession (fd, ref ms);
             
-            if(ms.xa_flag != 0) LastTrack--;
+            if(ms.xa_flag != 0) last_track--;
             
             return ret;
         }
         
-        int ReadTocEntry (int fd, byte track_number, ref ulong lba)
+        static int ReadTocEntry (int fd, byte track_number, ref ulong lba)
         {
             cdrom_tocentry te = new cdrom_tocentry ();
             te.cdte_track = track_number;
@@ -138,23 +134,23 @@
             return ReadTocEntry (fd, CDROM_LEADOUT, ref lba);
         }
         
-        internal LinuxDisc (string device)
+        internal DiscLinux (string device)
         {
             int fd = open (device, O_RDONLY | O_NONBLOCK);
             
-            if (fd < 0) throw new Exception (String.Format ("Cannot open device '{0}'", device));
+            if (fd < 0) throw new LocalDiscException (String.Format ("Cannot open device '{0}'", device));
             
-            try {
-                if (ReadTocHeader(fd) < 0) throw new Exception ("Cannot read table of contents");
-                if (LastTrack == 0) throw new Exception ("This disc has no tracks");
+            try {
+                if (ReadTocHeader (fd) < 0) throw new LocalDiscException ("Cannot read table of contents");
+                if (last_track == 0) throw new LocalDiscException ("This disc has no tracks");
                 
                 ulong lba = 0;
                 ReadLeadout (fd, ref lba);
-                TrackOffsets [0] = (int)lba + 150;
+                track_offsets [0] = (int)lba + 150;
                 
-                for (byte i = FirstTrack; i <= LastTrack; i++) {
+                for (byte i = first_track; i <= last_track; i++) {
                     ReadTocEntry (fd, i, ref lba);
-                    TrackOffsets[i] = (int)lba + 150;
+                    track_offsets[i] = (int)lba + 150;
                 }
             } finally {
                 close (fd);

Copied: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/DiscWin32.cs (from r5179, /trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Win32Disc.cs)
==============================================================================
--- /trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Win32Disc.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/DiscWin32.cs	Thu Apr  2 20:28:54 2009
@@ -1,6 +1,4 @@
-#region License
-
-// Win32Disc.cs
+// DiscWin32.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
 //
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Runtime.InteropServices;
 using System.Text;
@@ -31,17 +27,17 @@
 
 namespace MusicBrainz
 {
-    internal sealed class Win32Disc : LocalDisc
+    internal sealed class DiscWin32 : LocalDisc
     {
         [DllImport ("winmm")]
-        static extern Int32 mciSendString (String command, StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);
+        static extern Int32 mciSendString ([MarshalAs(UnmanagedType.LPTStr)] String command, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);
 
         [DllImport ("winmm")]
-        static extern Int32 mciGetErrorString (Int32 errorCode, StringBuilder errorText, Int32 errorTextSize);
+        static extern Int32 mciGetErrorString (Int32 errorCode, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder errorText, Int32 errorTextSize);
         
         delegate void MciCall (string result);
 
-        internal Win32Disc (string device)
+        internal DiscWin32 (string device)
         {
             string device_string = device.Length == 0 ? "cdaudio" : string.Format ("{0} type cdaudio", device);
 
@@ -53,7 +49,7 @@
                 "Could not get the list of CD audio devices",
                 delegate (string result) {
                     if (int.Parse (result.ToString ()) <= 0)
-                        throw new Exception ("No CD audio devices present.");
+                        throw new LocalDiscException ("No CD audio devices present.");
                 });
 
             MciClosure (
@@ -65,8 +61,8 @@
                 string.Format ("status {0} number of tracks wait", alias),
                 "Could not read number of tracks",
                 delegate (string result) {
-                    FirstTrack = 1;
-                    LastTrack = byte.Parse (result);
+                    first_track = 1;
+                    last_track = byte.Parse (result);
                 });
 
             MciClosure (
@@ -74,26 +70,26 @@
                 "Could not set time format",
                 null);
 
-            for (int i = 1; i <= LastTrack; i++)
+            for (int i = 1; i <= last_track; i++)
                 MciClosure (
                     string.Format ("status {0} position track {1} wait", alias, i),
                     string.Format ("Could not get position for track {0}", i),
                     delegate (string result) {
-                        TrackOffsets [i] =
+                        track_offsets [i] =
                             int.Parse (result.Substring (0,2)) * 4500 +
                             int.Parse (result.Substring (3,2)) * 75 +
                             int.Parse (result.Substring (6,2));
                     });
 
             MciClosure (
-                string.Format ("status {0} length track {1} wait", alias, LastTrack),
+                string.Format ("status {0} length track {1} wait", alias, last_track),
                 "Could not read the length of the last track",
                 delegate (string result) {
-                    TrackOffsets [0] =
+                    track_offsets [0] =
                         int.Parse (result.Substring (0, 2)) * 4500 +
                         int.Parse (result.Substring (3, 2)) * 75 +
                         int.Parse (result.Substring (6, 2)) +
-                        TrackOffsets [LastTrack] + 1;
+                        track_offsets [last_track] + 1;
                 });
 
             MciClosure (
@@ -111,7 +107,7 @@
             int ret = mciSendString (command, mci_result, mci_result.Capacity, IntPtr.Zero);
             if (ret != 0) {
                 mciGetErrorString (ret, mci_error, mci_error.Capacity);
-                throw new Exception (string.Format ("{0} : {1}", failure_message, mci_error.ToString ()));
+                throw new LocalDiscException (string.Format ("{0} : {1}", failure_message, mci_error.ToString ()));
             } else if (code != null) code (mci_result.ToString ());
         }
     }

Added: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/DiscWin32NT.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/DiscWin32NT.cs	Thu Apr  2 20:28:54 2009
@@ -0,0 +1,184 @@
+ï// DiscWin32NT.cs
+//
+// Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Runtime.InteropServices;
+using Microsoft.Win32.SafeHandles;
+
+namespace MusicBrainz
+{
+    internal sealed class DiscWin32NT : LocalDisc
+    {
+        [DllImport ("kernel32.dll")]
+        static extern bool DeviceIoControl (SafeFileHandle hDevice, uint dwIoControlCode,
+                                            IntPtr lpInBuffer, uint nInBufferSize,
+                                            IntPtr lpOutBuffer, uint nOutBufferSize,
+                                            out uint lpBytesReturned, IntPtr lpOverlapped);
+
+        [DllImport ("kernel32.dll")]
+        static extern SafeFileHandle CreateFile (string lpFileName, uint dwDesiredAccess,
+                                                 uint dwShareMode, IntPtr SecurityAttributes,
+                                                 uint dwCreationDisposition, uint dwFlagsAndAttributes,
+                                                 IntPtr hTemplateFile);
+
+        const uint GENERIC_READ = 0x80000000;
+        const uint FILE_SHARE_READ = 0x00000001;
+        const uint FILE_SHARE_WRITE = 0x00000002;
+
+        const uint OPEN_EXISTING = 3;
+
+        const uint IOCTL_CDROM_READ_TOC = 0x24000;
+        const uint IOCTL_CDROM_GET_LAST_SESSION = 0x24038;
+
+        const int XA_INTERVAL = ((60 + 90 + 2) * 75);
+
+        [StructLayout (LayoutKind.Sequential)]
+        struct TRACK_DATA
+        {
+            public byte Reserved;
+            public byte ControlAndAdr;
+            public byte TrackNumber;
+            public byte Reserved1;
+            public byte Address0;
+            public byte Address1;
+            public byte Address2;
+            public byte Address3;
+
+            public int GetSectors ()
+            {
+                return Address1 * 4500 + Address2 * 75 + Address3;
+            }
+        }
+
+        const int MAX_TRACK_NUMBER = 100;
+
+        [StructLayout (LayoutKind.Sequential)]
+        class CDROM_TOC
+        {
+            public ushort Length;
+            public byte FirstTrack;
+            public byte LastTrack;
+            public TRACK_DATA_Array TrackData = new TRACK_DATA_Array();
+            
+            public CDROM_TOC ()
+            {
+                Length = (ushort)Marshal.SizeOf (this);
+            }
+        }
+
+        [StructLayout (LayoutKind.Sequential)]
+        class TRACK_DATA_Array
+        {
+            [MarshalAs (UnmanagedType.ByValArray, SizeConst = MAX_TRACK_NUMBER * 8)]
+            byte[] TrackData = new byte[MAX_TRACK_NUMBER * Marshal.SizeOf (typeof (TRACK_DATA))];
+            public unsafe TRACK_DATA this[int index] {
+                get {
+                    if (index < 0 || index >= MAX_TRACK_NUMBER)
+                        throw new IndexOutOfRangeException ();
+
+                    fixed (byte* b = TrackData) {
+                        TRACK_DATA* td = (TRACK_DATA*)b;
+                        td += index;
+                        return *td;
+                    }
+                }
+            }
+        }
+
+        [StructLayout (LayoutKind.Sequential)]
+        class CDROM_TOC_SESSION_DATA
+        {
+            public ushort Length;
+            public byte FirstCompleteSession;
+            public byte LastCompleteSession;
+            public TRACK_DATA TrackData;
+
+            public CDROM_TOC_SESSION_DATA ()
+            {
+                Length = (ushort)Marshal.SizeOf (this);
+            }
+        }
+
+        internal DiscWin32NT (string device)
+        {
+            int colon = device.IndexOf (':');
+            if (colon == -1) {
+                throw new ArgumentException ("The device path is not valid.", "device");
+            }
+
+            string filename = string.Concat (@"\\.\", device.Substring (0, colon + 1));
+
+            CDROM_TOC_SESSION_DATA session = new CDROM_TOC_SESSION_DATA ();
+            CDROM_TOC toc = new CDROM_TOC();
+
+            using (SafeFileHandle file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero)) {
+
+                if (file.IsInvalid) {
+                    throw new LocalDiscException ("Could not open the CD device.");
+                }
+
+                uint returned;
+
+                GCHandle session_handle = GCHandle.Alloc (session, GCHandleType.Pinned);
+                try {
+                    bool result = DeviceIoControl (file, IOCTL_CDROM_GET_LAST_SESSION, IntPtr.Zero, 0,
+                        session_handle.AddrOfPinnedObject (), (uint)Marshal.SizeOf (session), out returned, IntPtr.Zero);
+                    if (!result) {
+                        throw new LocalDiscException ("There was a problem while reading the disc TOC.");
+                    }
+                } finally {
+                    session_handle.Free ();
+                }
+
+                IntPtr toc_ptr = Marshal.AllocHGlobal (Marshal.SizeOf (toc));
+                Marshal.StructureToPtr (toc, toc_ptr, false);
+                try {
+                    bool result = DeviceIoControl (file, IOCTL_CDROM_READ_TOC, IntPtr.Zero, 0,
+                        toc_ptr, (uint)Marshal.SizeOf (toc), out returned, IntPtr.Zero);
+                    if (!result) {
+                        throw new LocalDiscException ("There was a problem while reading the disc TOC.");
+                    }
+                    Marshal.PtrToStructure (toc_ptr, toc);
+                } finally {
+                    Marshal.FreeHGlobal (toc_ptr);
+                }
+            }
+
+            first_track = toc.FirstTrack;
+
+            if (session.FirstCompleteSession != session.LastCompleteSession) {
+                last_track = (byte)(session.TrackData.TrackNumber - 1);
+                track_offsets[0] = toc.TrackData[last_track].GetSectors () - XA_INTERVAL;
+            } else {
+                last_track = toc.LastTrack;
+                track_offsets[0] = toc.TrackData[last_track].GetSectors ();
+            }
+
+            for (int i = first_track; i <= last_track; i++) {
+                track_offsets[i] = toc.TrackData[i - 1].GetSectors ();
+            }
+
+            Init ();
+        }
+    }
+}
\ No newline at end of file

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Event.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Event.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Event.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // Event.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Xml;
 

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Label.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Label.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Label.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // Label.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Text;
 using System.Xml;
@@ -43,11 +39,7 @@
         
         #region Constructors
 
-        Label (string mbid) : base (mbid, null)
-        {
-        }
-
-        Label (string mbid, string parameters) : base (mbid, parameters)
+        Label (string id) : base (id, null)
         {
         }
 
@@ -59,71 +51,64 @@
         
         #region Protected
         
-        protected override string UrlExtension {
+        internal override string UrlExtension {
             get { return EXTENSION; }
         }
 
-        protected override void LoadMissingDataCore ()
+        internal override void LoadMissingDataCore ()
         {
-            Label label = new Label (Id, CreateInc ());
-            type = label.Type;
+            Label label = new Label (Id);
+            type = label.GetLabelType ();
+            country = label.GetCountry ();
             base.LoadMissingDataCore (label);
         }
 
-        protected override bool ProcessAttributes (XmlReader reader)
+        internal override void ProcessAttributes (XmlReader reader)
         {
             type = Utils.StringToEnum<LabelType> (reader ["type"]);
-            return this.type != null;
         }
 
-        protected override bool ProcessXml (XmlReader reader)
+        internal override void ProcessXmlCore (XmlReader reader)
         {
-            reader.Read ();
-            bool result = base.ProcessXml (reader);
-            if (!result) {
-                if (reader.Name == "country") {
-                    result = true;
-                    reader.Read ();
-                    if (reader.NodeType == XmlNodeType.Text)
-                        country = reader.ReadContentAsString ();
-                } else reader.Skip (); // FIXME this is a workaround for Mono bug 334752
-            }
-            reader.Close ();
-            return result;
+            if (reader.Name == "country") {
+                country = reader.ReadString ();
+            } else base.ProcessXmlCore (reader);
         }
         
         #endregion
 
-        #region Properties
+        #region Public
         
-        public string Country {
-            get { return GetPropertyOrNull (ref country); }
+        public string GetCountry ()
+        {
+            return GetPropertyOrNull (ref country);
         }
 
-        public LabelType Type {
-            get { return GetPropertyOrDefault (ref type, LabelType.None); }
+        public LabelType GetLabelType ()
+        {
+            return GetPropertyOrDefault (ref type, LabelType.None);
         }
         
         #endregion
         
         #region Static
 
-        public static Label Get (string mbid)
+        public static Label Get (string id)
         {
-            if (mbid == null) throw new ArgumentNullException ("mbid");
-            return new Label (mbid);
+            if (id == null) throw new ArgumentNullException ("id");
+            return new Label (id);
         }
 
         public static Query<Label> Query (string name)
         {
             if (name == null) throw new ArgumentNullException ("name");
-            return new Query<Label> (EXTENSION, QueryLimit, CreateNameParameter (name));
+            return new Query<Label> (EXTENSION, CreateNameParameter (name));
         }
 
         public static Query<Label> QueryLucene (string luceneQuery)
         {
             if (luceneQuery == null) throw new ArgumentNullException ("luceneQuery");
-            return new Query<Label> (EXTENSION, QueryLimit, CreateLuceneParameter (luceneQuery));
+            return new Query<Label> (EXTENSION, CreateLuceneParameter (luceneQuery));
         }
 
         public static implicit operator string (Label label)

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/LocalDisc.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/LocalDisc.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/LocalDisc.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // LocalDisc.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Security.Cryptography;
 using System.Text;
@@ -32,80 +28,86 @@
 {
     public abstract class LocalDisc : Disc
     {
-        public static string SubmissionServiceUrl = "http://mm.musicbrainz.org/bare/cdlookup.html";;
+        static Uri submission_service_url = new Uri("http://mm.musicbrainz.org/bare/cdlookup.html";);
+        public static Uri SubmissionServiceUrl {
+            get { return submission_service_url; }
+            set {
+                if (value == null) throw new ArgumentNullException ("value");
+                submission_service_url = value;
+            }
+        }
         
-        byte first_track;
-        byte last_track;
-        int [] track_durations;
-        int [] track_offsets = new int [100];
+        internal byte first_track;
+        internal byte last_track;
+        internal int [] track_offsets = new int [100];
+        TimeSpan [] track_durations;
         
         internal LocalDisc()
         {
         }
         
-        protected void Init ()
+        internal void Init ()
         {
-            track_durations = new int [last_track];
+            track_durations = new TimeSpan [last_track];
             for (int i = 1; i <= last_track; i++) {
-                track_durations [i - 1] = i < last_track
-                    ? track_offsets [i + 1] - track_offsets [i]
-                    : track_offsets [0] - track_offsets [i];
-                track_durations [i - 1] /= 75; // 75 frames in a second
+                track_durations [i - 1] = TimeSpan.FromSeconds (
+                    ((i < last_track ? track_offsets [i + 1] : track_offsets [0]) - track_offsets [i]) / 75); // 75 frames in a second
             }
             GenerateId ();
         }
         
         void GenerateId ()
         {
-            StringBuilder input_builder = new StringBuilder (804);
-            
-            input_builder.Append (string.Format ("{0:X2}", FirstTrack));
-            input_builder.Append (string.Format ("{0:X2}", LastTrack));
+            StringBuilder input_builder = new StringBuilder (804);
+
+            input_builder.AppendFormat ("{0:X2}", first_track);
+            input_builder.AppendFormat ("{0:X2}", last_track);
             
-            for (int i = 0; i < track_offsets.Length; i++)
-                input_builder.Append (string.Format ("{0:X8}", track_offsets [i]));
+            for (int i = 0; i < track_offsets.Length; i++)
+                input_builder.AppendFormat ("{0:X8}", track_offsets[i]);
 
             // MB uses a slightly modified RFC822 for reasons of URL happiness.
-            string base64 = Convert.ToBase64String (SHA1.Create ()
-                .ComputeHash (Encoding.ASCII.GetBytes (input_builder.ToString ())));
+            string base64 = Convert.ToBase64String (SHA1.Create ().
+                ComputeHash (Encoding.ASCII.GetBytes (input_builder.ToString ())));
             StringBuilder hash_builder = new StringBuilder (base64.Length);
             
-            foreach (char c in base64)
-                if      (c == '+')  hash_builder.Append ('.');
-                else if (c == '/')  hash_builder.Append ('_');
-                else if (c == '=')  hash_builder.Append ('-');
-                else                hash_builder.Append (c);
+            foreach (char c in base64)
+                switch (c) {
+                case '+':
+                    hash_builder.Append ('.');
+                    break;
+                case '/':
+                    hash_builder.Append ('_');
+                    break;
+                case '=':
+                    hash_builder.Append ('-');
+                    break;
+                default:
+                    hash_builder.Append (c);
+                    break;
+                }
             
             Id = hash_builder.ToString ();
         }
         
-        protected byte FirstTrack {
-            get { return first_track; }
-            set { first_track = value; }
-        }
-
-        protected byte LastTrack {
-            get { return last_track; }
-            set { last_track = value; }
-        }
-
-        protected int [] TrackOffsets {
-            get { return track_offsets; }
-        }
-        
-        public int [] TrackDurations {
-            get { return track_durations; }
+        public TimeSpan [] GetTrackDurations ()
+        {
+            return (TimeSpan []) track_durations.Clone ();
         }
         
-        string submission_url;
-        public string SubmissionUrl {
-            get { return submission_url ?? (submission_url = BuildSubmissionUrl ()); }
+        Uri submission_url;
+        public Uri SubmissionUrl {
+            get {
+                if (submission_url == null) {
+                    submission_url = BuildSubmissionUrl ();
+                }
+                return submission_url; }
         }
         
-        string BuildSubmissionUrl ()
+        Uri BuildSubmissionUrl ()
         {
             StringBuilder builder = new StringBuilder ();
-            builder.Append (SubmissionServiceUrl);
+            builder.Append (SubmissionServiceUrl.AbsoluteUri);
             builder.Append ("?id=");
             builder.Append (Id);
             builder.Append ("&tracks=");
@@ -120,15 +122,34 @@
                 builder.Append ('+');
                 builder.Append (track_offsets [i]);
             }
-            return builder.ToString ();
+            return new Uri(builder.ToString ());
         }
         
         public static LocalDisc GetFromDevice (string device)
         {
             if (device == null) throw new ArgumentNullException ("device");
-            return Environment.OSVersion.Platform != PlatformID.Unix
-                ? (LocalDisc)new Win32Disc (device)
-                : new LinuxDisc (device);
+            try {
+                switch (Environment.OSVersion.Platform){
+                case PlatformID.Unix:
+                    return new DiscLinux (device);
+                //case PlatformID.Win32NT:
+                    //return new DiscWin32NT (device);
+                default:
+                    return new DiscWin32 (device);
+                }
+            } catch (Exception exception) {
+                throw new LocalDiscException (exception);
+            }
+        }
+    }
+    
+    public class LocalDiscException : Exception
+    {
+        public LocalDiscException (string message) : base (message)
+        {
+        }
+        public LocalDiscException (Exception exception) : base ("Could not load local disc from device.", exception)
+        {
         }
     }
 }

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzEntity.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzEntity.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzEntity.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // MusicBrainzEntity.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -49,7 +45,7 @@
         
         #region Constructors
         
-        internal MusicBrainzEntity (string mbid, string parameters) : base (mbid, parameters)
+        internal MusicBrainzEntity (string id, string parameters) : base (id, parameters)
         {
         }
 
@@ -61,41 +57,34 @@
         
         #region Protected
 
-        protected override void CreateIncCore (StringBuilder builder)
+        internal override void CreateIncCore (StringBuilder builder)
         {
             if (aliases == null) AppendIncParameters (builder, "aliases");
             base.CreateIncCore (builder);
         }
 
-        protected void LoadMissingDataCore (MusicBrainzEntity entity)
+        internal void LoadMissingDataCore (MusicBrainzEntity entity)
         {
-            name = entity.Name;
-            sort_name = entity.SortName;
-            disambiguation = entity.Disambiguation;
-            begin_date = entity.BeginDate;
-            end_date = entity.EndDate;
-            if (aliases == null) aliases = entity.Aliases;
+            name = entity.GetName ();
+            sort_name = entity.GetSortName ();
+            disambiguation = entity.GetDisambiguation ();
+            begin_date = entity.GetBeginDate ();
+            end_date = entity.GetEndDate ();
+            if (aliases == null) aliases = entity.GetAliases ();
             base.LoadMissingDataCore (entity);
-        }
-
-        protected override bool ProcessXml (XmlReader reader)
+        }
+
+        internal override void ProcessXmlCore (XmlReader reader)
         {
-            bool result = true;
             switch (reader.Name) {
-            case "name":
-                reader.Read ();
-                if (reader.NodeType == XmlNodeType.Text)
-                    name = reader.ReadContentAsString ();
-                break;
-            case "sort-name":
-                reader.Read ();
-                if (reader.NodeType == XmlNodeType.Text)
-                    sort_name = reader.ReadContentAsString ();
-                break;
-            case "disambiguation":
-                reader.Read ();
-                if (reader.NodeType == XmlNodeType.Text)
-                    disambiguation = reader.ReadContentAsString ();
+            case "name":
+                name = reader.ReadString ();
+                break;
+            case "sort-name":
+                sort_name = reader.ReadString ();
+                break;
+            case "disambiguation":
+                disambiguation = reader.ReadString ();
                 break;
             case "life-span":
                 begin_date = reader ["begin"];
@@ -104,62 +93,63 @@
             case "alias-list":
                 if (reader.ReadToDescendant ("alias")) {
                     List<string> aliases = new List<string> ();
-                    do {
-                        reader.Read ();
-                        if (reader.NodeType == XmlNodeType.Text)
-                            aliases.Add (reader.ReadContentAsString ());
-                    } while (reader.ReadToNextSibling ("alias"));
+                    do aliases.Add (reader.ReadString ());
+                    while (reader.ReadToNextSibling ("alias"));
                     this.aliases = aliases.AsReadOnly ();
                 }
                 break;
-            default:
-                result = false;
+            default:
+                base.ProcessXmlCore (reader);
                 break;
             }
-            return result;
         }
         
-        protected static string CreateNameParameter (string name)
+        internal static string CreateNameParameter (string name)
         {
-            return "&name=" + Utils.PercentEncode (name);
+            StringBuilder builder = new StringBuilder (name.Length + 6);
+            builder.Append ("&name=");
+            Utils.PercentEncode (builder, name);
+            return builder.ToString ();
         }
         
         #endregion
 
-        #region Properties
+        #region Public
 
-        public virtual string Name {
-            get { return GetPropertyOrNull (ref name); }
+        public virtual string GetName ()
+        {
+            return GetPropertyOrNull (ref name);
         }
 
-        [Queryable]
-        public virtual string SortName {
-            get { return GetPropertyOrNull (ref sort_name); }
+        [Queryable ("sortname")]
+        public virtual string GetSortName ()
+        {
+            return GetPropertyOrNull (ref sort_name);
         }
 
         [Queryable ("comment")]
-        public virtual string Disambiguation {
-            get { return GetPropertyOrNull (ref disambiguation); }
+        public virtual string GetDisambiguation ()
+        {
+            return GetPropertyOrNull (ref disambiguation);
         }
 
         [Queryable ("begin")]
-        public virtual string BeginDate {
-            get { return GetPropertyOrNull (ref begin_date); }
+        public virtual string GetBeginDate ()
+        {
+            return GetPropertyOrNull (ref begin_date);
         }
 
         [Queryable ("end")]
-        public virtual string EndDate {
-            get { return GetPropertyOrNull (ref end_date); }
+        public virtual string GetEndDate ()
+        {
+            return GetPropertyOrNull (ref end_date);
         }
 
         [QueryableMember ("Contains", "alias")]
-        public virtual ReadOnlyCollection<string> Aliases {
-            get { return GetPropertyOrNew (ref aliases); }
+        public virtual ReadOnlyCollection<string> GetAliases ()
+        {
+            return GetPropertyOrNew (ref aliases);
         }
-
-        #endregion
-
-        #region Public
         
         public override string ToString ()
         {

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzException.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzException.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzException.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // MusicBrainzException.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 
 namespace MusicBrainz
@@ -31,7 +27,7 @@
     public sealed class MusicBrainzInvalidParameterException : Exception
     {
         public MusicBrainzInvalidParameterException ()
-            : base ("One of the parameters is invalid. The MBID may be invalid, or you may be using an illegal parameter for this resource type.")
+            : base ("One of the parameters is invalid. The ID may be invalid, or you may be using an illegal parameter for this resource type.")
         {
         }
     }

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzItem.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzItem.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzItem.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // MusicBrainzItem.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Text;
 using System.Xml;
@@ -43,7 +39,7 @@
         
         #region Constructors
         
-        internal MusicBrainzItem (string mbid, string parameters) : base (mbid, parameters)
+        internal MusicBrainzItem (string id) : base (id, null)
         {
         }
 
@@ -56,55 +52,49 @@
         
         #region Protected Overrides
 
-        protected override void CreateIncCore (StringBuilder builder)
+        internal override void CreateIncCore (StringBuilder builder)
         {
             if (artist == null) AppendIncParameters(builder, "artist");
             base.CreateIncCore (builder);
         }
 
-        protected void LoadMissingDataCore (MusicBrainzItem item)
+        internal void LoadMissingDataCore (MusicBrainzItem item)
         {
-            title = item.Title;
-            if (artist == null) artist = item.Artist;
+            title = item.GetTitle ();
+            if (artist == null) artist = item.GetArtist ();
             base.LoadMissingDataCore (item);
         }
 
-        protected override bool ProcessXml (XmlReader reader)
+        internal override void ProcessXmlCore (XmlReader reader)
         {
-            bool result = true;
             switch (reader.Name) {
-            case "title":
-                reader.Read ();
-                if (reader.NodeType == XmlNodeType.Text)
-                    title = reader.ReadContentAsString ();
+            case "title":
+                title = reader.ReadString ();
                 break;
             case "artist":
                 artist = new Artist (reader.ReadSubtree ());
                 break;
-            default:
-                result = false;
+            default:
+                base.ProcessXmlCore (reader);
                 break;
             }
-            return result;
         }
         
         #endregion
 
-        #region Properties
+        #region Public
         
-        public virtual string Title {
-            get { return GetPropertyOrNull (ref title); }
+        public virtual string GetTitle ()
+        {
+            return GetPropertyOrNull (ref title);
         }
 
         [Queryable ("artist")]
-        public virtual Artist Artist {
-            get { return GetPropertyOrNull (ref artist); }
+        public virtual Artist GetArtist ()
+        {
+            return GetPropertyOrNull (ref artist);
         }
         
-        #endregion
-
-        #region Public
-        
         public override string ToString ()
         {
             return title;
@@ -158,8 +148,12 @@
             set { count = value; }
         }
 
-        protected void AppendBaseToBuilder (StringBuilder builder)
+        internal abstract void ToStringCore (StringBuilder builder);
+        
+        public override string ToString ()
         {
+            StringBuilder builder = new StringBuilder ();
+            ToStringCore (builder);
             if (title != null) {
                 builder.Append ("&title=");
                 Utils.PercentEncode (builder, title);
@@ -184,6 +178,7 @@
                 builder.Append ("&count=");
                 builder.Append (count.Value);
             }
+            return builder.ToString ();
         }
     }
     

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzObject.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzObject.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzObject.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // MusicBrainzObject.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -67,10 +63,10 @@
         
         #region Constructors
 
-        internal MusicBrainzObject (string mbid, string parameters)
+        internal MusicBrainzObject (string id, string parameters)
         {
             all_data_loaded = true;
-            CreateFromMbid (mbid, parameters ?? CreateInc ());
+            CreateFromId (id, parameters ?? CreateInc ());
         }
 
         internal MusicBrainzObject (XmlReader reader, bool all_rels_loaded)
@@ -81,12 +77,19 @@
         
         #endregion
         
-        #region Private Methods
+        #region Private Methods
+
+        string CreateInc ()
+        {
+            StringBuilder builder = new StringBuilder ();
+            CreateIncCore (builder);
+            return builder.ToString ();
+        }
         
-        void CreateFromMbid (string mbid, string parameters)
+        void CreateFromId (string id, string parameters)
         {
             XmlProcessingClosure (
-                CreateUrl (UrlExtension, mbid, parameters),
+                CreateUrl (UrlExtension, id, parameters),
                 delegate (XmlReader reader) {
                     reader.ReadToFollowing ("metadata");
                     reader.Read ();
@@ -107,86 +110,60 @@
                     all_rels_loaded = true;
                     switch (reader ["target-type"]) {
                     case "Artist":
-                        List<Relation<Artist>> artist_rels = new List<Relation<Artist>> ();
-                        CreateRelation (reader.ReadSubtree (), artist_rels);
-                        this.artist_rels = artist_rels.AsReadOnly ();
+                        artist_rels = CreateRelation<Artist> (reader.ReadSubtree ());
                         break;
                     case "Release":
-                        List<Relation<Release>> release_rels = new List<Relation<Release>> ();
-                        CreateRelation (reader.ReadSubtree (), release_rels);
-                        this.release_rels = release_rels.AsReadOnly ();
+                        release_rels = CreateRelation<Release> (reader.ReadSubtree ());
                         break;
                     case "Track":
-                        List<Relation<Track>> track_rels = new List<Relation<Track>> ();
-                        CreateRelation (reader.ReadSubtree (), track_rels);
-                        this.track_rels = track_rels.AsReadOnly ();
+                        track_rels = CreateRelation<Track> (reader.ReadSubtree ());
                         break;
                     case "Label":
-                        List<Relation<Label>> label_rels = new List<Relation<Label>> ();
-                        CreateRelation (reader.ReadSubtree (), label_rels);
-                        this.label_rels = label_rels.AsReadOnly ();
+                        label_rels = CreateRelation<Label> (reader.ReadSubtree ());
                         break;
-                    case "Url":
-                        if (!reader.ReadToDescendant ("relation")) break;
-                        List<UrlRelation> url_rels = new List<UrlRelation> ();
-                        do {
-                            RelationDirection direction = RelationDirection.Forward;
-                            string direction_string = reader ["direction"];
-                            if (direction_string != null && direction_string == "backward")
-                                direction = RelationDirection.Backward;
-                            string attributes_string = reader ["attributes"];
-                            string [] attributes = attributes_string == null
-                                ? null : attributes_string.Split (' ');
-                            url_rels.Add (new UrlRelation (
-                                reader ["type"],
-                                reader ["target"],
-                                direction,
-                                reader ["begin"],
-                                reader ["end"],
-                                attributes));
-                        } while (reader.ReadToNextSibling ("relation"));
-                        this.url_rels = url_rels.AsReadOnly ();
+                    case "Url":
+                        url_rels = CreateUrlRelation (reader.ReadSubtree ());
                         break;
                     }
                 } else
                     ProcessXml (reader.ReadSubtree ());
             }
             reader.Close ();
+        }
+
+        void ProcessXml (XmlReader reader)
+        {
+            reader.Read ();
+            ProcessXmlCore (reader);
+            reader.Close ();
         }
         
         #endregion
         
         #region Protected
         
-        protected bool AllDataLoaded {
+        internal bool AllDataLoaded {
             get { return all_data_loaded; }
         }
         
-        protected bool AllRelsLoaded {
+        internal bool AllRelsLoaded {
             get { return all_rels_loaded; }
             set { all_rels_loaded = value; }
         }
         
-        protected string CreateInc ()
-        {
-            StringBuilder builder = new StringBuilder ();
-            CreateIncCore (builder);
-            return builder.ToString ();
-        }
-        
-        protected virtual void CreateIncCore (StringBuilder builder)
+        internal virtual void CreateIncCore (StringBuilder builder)
         {
             if (!all_rels_loaded)
                 AppendIncParameters (builder, rels_params);
         }
         
-        protected void AppendIncParameters (StringBuilder builder, string parameter)
+        internal static void AppendIncParameters (StringBuilder builder, string parameter)
         {
             builder.Append (builder.Length == 0 ? "&inc=" : "+");
             builder.Append (parameter);
         }
         
-        protected void AppendIncParameters (StringBuilder builder, string parameter1, string parameter2)
+        internal static void AppendIncParameters (StringBuilder builder, string parameter1, string parameter2)
         {
             builder.Append (builder.Length == 0 ? "&inc=" : "+");
             builder.Append (parameter1);
@@ -194,13 +171,13 @@
             builder.Append (parameter2);
         }
 
-        protected void AppendIncParameters (StringBuilder builder, string [] parameters)
+        internal static void AppendIncParameters (StringBuilder builder, string [] parameters)
         {
             foreach (string parameter in parameters)
                 AppendIncParameters (builder, parameter);
         }
         
-        protected void LoadMissingData ()
+        internal void LoadMissingData ()
         {
             if (!all_data_loaded) {
                 LoadMissingDataCore ();
@@ -208,48 +185,60 @@
             }
         }
 
-        protected void LoadMissingDataCore (MusicBrainzObject obj)
+        internal void LoadMissingDataCore (MusicBrainzObject obj)
         {
             if (!all_rels_loaded) {
-                artist_rels = obj.ArtistRelations;
-                release_rels = obj.ReleaseRelations;
-                track_rels = obj.TrackRelations;
-                label_rels = obj.LabelRelations;
-                url_rels = obj.UrlRelations;
+                artist_rels = obj.GetArtistRelations ();
+                release_rels = obj.GetReleaseRelations ();
+                track_rels = obj.GetTrackRelations ();
+                label_rels = obj.GetLabelRelations ();
+                url_rels = obj.GetUrlRelations ();
             }
         }
         
-        protected abstract void LoadMissingDataCore ();
-        protected abstract bool ProcessAttributes (XmlReader reader);
-        protected abstract bool ProcessXml (XmlReader reader);
-        protected abstract string UrlExtension { get; }
-        
-        #endregion
-        
-        #region Properties
-        
-        protected T GetPropertyOrNull<T> (ref T field_reference) where T : class
+        internal T GetPropertyOrNull<T> (ref T field_reference) where T : class
         {
             if (field_reference == null) LoadMissingData ();
             return field_reference;
         }
+
+        internal T GetPropertyOrDefault<T> (ref T? field_reference) where T : struct
+        {
+            return GetPropertyOrDefault (ref field_reference, default (T));
+        }
         
-        protected T GetPropertyOrDefault<T> (ref T? field_reference, T default_value) where T : struct
+        internal T GetPropertyOrDefault<T> (ref T? field_reference, T default_value) where T : struct
         {
             if (field_reference == null) LoadMissingData ();
             return field_reference ?? default_value;
         }
         
-        protected ReadOnlyCollection<T> GetPropertyOrNew<T> (ref ReadOnlyCollection<T> field_reference)
+        internal ReadOnlyCollection<T> GetPropertyOrNew<T> (ref ReadOnlyCollection<T> field_reference)
         {
             return GetPropertyOrNew (ref field_reference, true);
         }
         
-        protected ReadOnlyCollection<T> GetPropertyOrNew<T> (ref ReadOnlyCollection<T> field_reference, bool condition)
+        internal ReadOnlyCollection<T> GetPropertyOrNew<T> (ref ReadOnlyCollection<T> field_reference, bool condition)
         {
             if (field_reference == null && condition) LoadMissingData ();
             return field_reference ?? new ReadOnlyCollection<T> (new T [0]);
+        }
+
+        internal virtual void ProcessXmlCore (XmlReader reader)
+        {
+            reader.Skip (); // FIXME this is a workaround for Mono bug 334752
+        }
+
+        internal virtual void ProcessAttributes (XmlReader reader)
+        {
         }
+        
+        internal abstract void LoadMissingDataCore ();
+        internal abstract string UrlExtension { get; }
+        
+        #endregion
+        
+        #region Public
 
         public virtual string Id {
             get { return id; }
@@ -259,34 +248,47 @@
             get { return score; }
         }
 
-        public virtual ReadOnlyCollection<Relation<Artist>> ArtistRelations {
-            get { return GetPropertyOrNew (ref artist_rels, !all_rels_loaded); }
+        public virtual ReadOnlyCollection<Relation<Artist>> GetArtistRelations ()
+        {
+            return GetPropertyOrNew (ref artist_rels, !all_rels_loaded);
         }
 
-        public virtual ReadOnlyCollection<Relation<Release>> ReleaseRelations {
-            get { return GetPropertyOrNew (ref release_rels, !all_rels_loaded); }
+        public virtual ReadOnlyCollection<Relation<Release>> GetReleaseRelations ()
+        {
+            return GetPropertyOrNew (ref release_rels, !all_rels_loaded);
         }
 
-        public virtual ReadOnlyCollection<Relation<Track>> TrackRelations {
-            get { return GetPropertyOrNew (ref track_rels, !all_rels_loaded); }
+        public virtual ReadOnlyCollection<Relation<Track>> GetTrackRelations ()
+        {
+            return GetPropertyOrNew (ref track_rels, !all_rels_loaded);
         }
 
-        public virtual ReadOnlyCollection<Relation<Label>> LabelRelations {
-            get { return GetPropertyOrNew (ref label_rels, !all_rels_loaded); }
+        public virtual ReadOnlyCollection<Relation<Label>> GetLabelRelations ()
+        {
+            return GetPropertyOrNew (ref label_rels, !all_rels_loaded);
         }
 
-        public virtual ReadOnlyCollection<UrlRelation> UrlRelations {
-            get { return GetPropertyOrNew (ref url_rels, !all_rels_loaded); }
+        public virtual ReadOnlyCollection<UrlRelation> GetUrlRelations ()
+        {
+            return GetPropertyOrNew (ref url_rels, !all_rels_loaded);
         }
-
-        #endregion
-        
-        #region Public
         
         public override bool Equals (object obj)
         {
-            MusicBrainzObject mbobj = obj as MusicBrainzObject;
-            return mbobj != null && mbobj.GetType ().Equals (GetType ()) && mbobj.Id == Id;
+            return this == obj as MusicBrainzObject;
+        }
+        
+        public static bool operator ==(MusicBrainzObject obj1, MusicBrainzObject obj2)
+        {
+            if (Object.ReferenceEquals (obj1, null)) {
+                return Object.ReferenceEquals (obj2, null);
+            }
+            return !Object.ReferenceEquals (obj2, null) && obj1.GetType () == obj2.GetType () && obj1.Id == obj2.Id;
+        }
+        
+        public static bool operator !=(MusicBrainzObject obj1, MusicBrainzObject obj2)
+        {
+            return !(obj1 == obj2);
         }
 
         public override int GetHashCode ()
@@ -298,8 +300,9 @@
 
         #region Static
 
-        static void CreateRelation<T> (XmlReader reader, List<Relation<T>> relations) where T : MusicBrainzObject
+        static ReadOnlyCollection<Relation<T>> CreateRelation<T> (XmlReader reader) where T : MusicBrainzObject
         {
+            List<Relation<T>> relations = new List<Relation<T>> ();
             while (reader.ReadToFollowing ("relation")) {
                 string type = reader ["type"];
                 RelationDirection direction = RelationDirection.Forward;
@@ -322,6 +325,29 @@
                     attributes));
             }
             reader.Close ();
+            return relations.AsReadOnly ();
+        }
+
+        static ReadOnlyCollection<UrlRelation> CreateUrlRelation (XmlReader reader)
+        {
+            List<UrlRelation> url_rels = new List<UrlRelation> ();
+            while (reader.ReadToDescendant ("relation")) {
+                RelationDirection direction = RelationDirection.Forward;
+                string direction_string = reader["direction"];
+                if (direction_string != null && direction_string == "backward")
+                    direction = RelationDirection.Backward;
+                string attributes_string = reader["attributes"];
+                string[] attributes = attributes_string == null
+                    ? null : attributes_string.Split (' ');
+                url_rels.Add (new UrlRelation (
+                    reader["type"],
+                    reader["target"],
+                    direction,
+                    reader["begin"],
+                    reader["end"],
+                    attributes));
+            }
+            return url_rels.AsReadOnly ();
         }
 
         static string CreateUrl (string url_extension, int limit, int offset, string parameters)
@@ -339,14 +365,14 @@
             return CreateUrl (url_extension, string.Empty, builder.ToString ());
         }
 
-        static string CreateUrl (string url_extension, string mbid, string parameters)
+        static string CreateUrl (string url_extension, string id, string parameters)
         {
             StringBuilder builder = new StringBuilder (
-                MusicBrainzService.ServiceUrl.Length + mbid.Length + parameters.Length + 9);
-            builder.Append (MusicBrainzService.ServiceUrl);
+                MusicBrainzService.ServiceUrl.AbsoluteUri.Length + id.Length + parameters.Length + 9);
+            builder.Append (MusicBrainzService.ServiceUrl.AbsoluteUri);
             builder.Append (url_extension);
             builder.Append ('/');
-            builder.Append (mbid);
+            builder.Append (id);
             builder.Append ("?type=xml");
             builder.Append (parameters);
             return builder.ToString ();
@@ -359,9 +385,9 @@
             // Don't access the MB server twice within a second
             TimeSpan time = DateTime.Now - last_accessed;
             if (min_interval > time)
-                Thread.Sleep ((min_interval - time).Milliseconds);
-
-            HttpWebRequest request = WebRequest.Create (url) as HttpWebRequest;
+                Thread.Sleep ((min_interval - time).Milliseconds);
+
+            WebRequest request = WebRequest.Create (url);
             bool cache_implemented = false;
             
             try {
@@ -372,7 +398,7 @@
             HttpWebResponse response = null;
             
             try {
-                response = request.GetResponse () as HttpWebResponse;
+                response = (HttpWebResponse)request.GetResponse ();
             } catch (WebException e) {
                 response = (HttpWebResponse)e.Response;
             }
@@ -391,12 +417,12 @@
                 throw new MusicBrainzNotFoundException ();
             }
 
-            bool from_cache = cache_implemented && response.IsFromCache;
+            bool from_cache = cache_implemented && response.IsFromCache;
+
+            if (from_cache) Monitor.Exit (server_mutex);
 
             MusicBrainzService.OnXmlRequest (url, from_cache);
 
-            if (from_cache) Monitor.Exit (server_mutex);
-
             // Should we read the stream into a memory stream and run the XmlReader off of that?
             code (new XmlTextReader (response.GetResponseStream ()));
             response.Close ();
@@ -411,17 +437,16 @@
 
         #region Query
 
-        protected static byte QueryLimit {
-            get { return 100; }
-        }
-
-        protected static string CreateLuceneParameter (string query)
+        internal static string CreateLuceneParameter (string query)
         {
-            return "&query=" + Utils.PercentEncode (query);
+            StringBuilder builder = new StringBuilder (query.Length + 7);
+            builder.Append ("&query=");
+            Utils.PercentEncode (builder, query);
+            return builder.ToString ();
         }
 
         internal static List<T> Query<T> (string url_extension,
-                                          byte limit, int offset,
+                                          int limit, int offset,
                                           string parameters,
                                           out int? count) where T : MusicBrainzObject
         {

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzService.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzService.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/MusicBrainzService.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // MusicBrainzService.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Net.Cache;
 
@@ -31,14 +27,27 @@
 {
     public static class MusicBrainzService
     {
-        public static string ServiceUrl = @"http://musicbrainz.org/ws/1/";;
-        public static RequestCachePolicy CachePolicy;
+        static Uri service_url = new Uri (@"http://musicbrainz.org/ws/1/";);
+        public static Uri ServiceUrl {
+            get { return service_url; }
+            set {
+                if (value == null) throw new ArgumentNullException ("value");
+                service_url = value;
+            }
+        }
+        
+        static RequestCachePolicy cache_policy;
+        public static RequestCachePolicy CachePolicy {
+            get { return cache_policy; }
+            set { cache_policy = value; }
+        }
+        
         public static event EventHandler<XmlRequestEventArgs> XmlRequest;
         
         internal static void OnXmlRequest (string url, bool fromCache)
         {
             EventHandler<XmlRequestEventArgs> handler = XmlRequest;
-            if (handler != null) handler (null, new XmlRequestEventArgs (url, fromCache));
+            if (handler != null) handler (null, new XmlRequestEventArgs (new Uri (url), fromCache));
         }
     }
 }

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Query.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Query.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Query.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // Query.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -35,10 +31,12 @@
     {
         
         #region Private
+
+        const int default_limit = 100;
         
         string parameters;
         string url_extension;
-        byte limit;
+        int limit = default_limit;
         
         int offset;
         int? count;
@@ -46,10 +44,15 @@
         List<T> results;
         List<T> ResultsWindow {
             get {
-                if (results == null)
-                    results = MusicBrainzObject.Query<T> (url_extension, limit, offset, parameters, out count);
+                if (results == null)
+                    LoadResults ();
                 return results;
             }
+        }
+
+        void LoadResults ()
+        {
+            results = MusicBrainzObject.Query<T> (url_extension, limit, offset, parameters, out count);
         }
 
         Dictionary<int, WeakReference> weak_references = new Dictionary<int, WeakReference> ();
@@ -67,7 +70,7 @@
                 if (weak_references.ContainsKey (offset)) {
                     WeakReference weak_reference = weak_references [offset];
                     if (weak_reference.IsAlive)
-                        results = weak_reference.Target as List<T>;
+                        results = (List<T>)weak_reference.Target;
                 }
             }
         }
@@ -76,10 +79,9 @@
 
         #region Constructors
         
-        internal Query (string url_extension, byte limit, string parameters)
+        internal Query (string url_extension, string parameters)
         {
             this.url_extension = url_extension;
-            this.limit = limit;
             this.parameters = parameters;
         }
         
@@ -88,24 +90,25 @@
         #region Public
         
         public int Count {
-            get {
-                if(count == null && ResultsWindow == null) { } // just accessing ResultsWindow will give count a value
+            get {
+                if (count == null)
+                    LoadResults ();
                 return count.Value;
             }
         }
 
-        public T this [int i] {
-            get {
-                if (i < 0 || i >= Count) throw new IndexOutOfRangeException ();
-                if (i <= offset || i >= offset + limit) 
-                    Offset = i;
-                return ResultsWindow [i - offset];
+        public T this [int index] {
+            get {
+                if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException ("index");
+                if (index < offset || index >= offset + limit)
+                    Offset = index;
+                return ResultsWindow[index - offset];
             }
         }
         
         public T First ()
         {
-            byte tmp_limit = limit;
+            int tmp_limit = limit;
             limit = 1;
             T result = Count > 0 ? this [0] : null;
             limit = tmp_limit;
@@ -113,8 +116,8 @@
         }
         
         public T PerfectMatch ()
-        {
-            byte tmp_limit = limit;
+        {
+            int tmp_limit = limit;
             limit = 2;
             T result1 = Count > 0 ? this [0] : null;
             T result2 = Count > 1 ? this [1] : null;
@@ -129,33 +132,14 @@
             return Best (100);
         }
         
-        public IEnumerable<T> Best (int score_threshold)
+        public IEnumerable<T> Best (int scoreThreshold)
         {
             foreach (T result in this) {
-                if (result.Score < score_threshold) yield break;
+                if (result.Score < scoreThreshold) yield break;
                 yield return result;
             }
         }
         
-        public List<T> ToList ()
-        {
-            return ToList (0);
-        }
-        
-        public List<T> ToList (int score_threshold)
-        {
-            List<T> list = new List<T> (score_threshold == 0 ? Count : 0);
-            foreach (T result in Best(score_threshold)) list.Add (result);
-            return list;
-        }
-        
-        public T [] ToArray ()
-        {
-            T [] array = new T [Count];
-            for(int i = 0; i < Count; i++) array [i] = this [i];
-            return array;
-        }
-        
         public IEnumerator<T> GetEnumerator ()
         {
             for (int i = 0; i < Count; i++) yield return this [i];
@@ -175,31 +159,39 @@
         
     }
 
-    [AttributeUsage (AttributeTargets.Property)]
+    [AttributeUsage (AttributeTargets.Method | AttributeTargets.Property)]
     internal sealed class QueryableAttribute : Attribute
     {
-        public readonly string Name;
+        readonly string name;
         
-        public QueryableAttribute ()
+        public QueryableAttribute (string name)
         {
+            this.name = name;
         }
         
-        public QueryableAttribute (string name)
-        {
-            Name = name;
+        public string Name {
+            get { return name; }
         }
     }
 
-    [AttributeUsage (AttributeTargets.Property)]
+    [AttributeUsage (AttributeTargets.Method | AttributeTargets.Property)]
     internal sealed class QueryableMemberAttribute : Attribute
     {
-        public readonly string Name;
-        public readonly string Member;
+        readonly string member;
+        readonly string name;
         
         public QueryableMemberAttribute (string member, string name)
         {
-            Member = member;
-            Name = name;
+            this.member = member;
+            this.name = name;
+        }
+        
+        public string Member {
+            get { return member; }
+        }
+        
+        public string Name {
+            get { return name; }
         }
     }
 }

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Relation.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Relation.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Relation.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // Relation.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,9 +20,8 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
+using System.Collections.ObjectModel;
 
 namespace MusicBrainz
 {
@@ -32,7 +29,7 @@
     {
         T target;
         string type;
-        string [] attributes;
+        ReadOnlyCollection<string> attributes;
         RelationDirection direction;
         string begin;
         string end;
@@ -45,7 +42,7 @@
             this.direction = direction;
             this.begin = begin;
             this.end = end;
-            this.attributes = attributes;
+            this.attributes = new ReadOnlyCollection<string> (attributes ?? new string [0]);
         }
 
         public T Target {
@@ -56,7 +53,7 @@
             get { return type; }
         }
 
-        public string [] Attributes {
+        public ReadOnlyCollection<string> Attributes {
             get { return attributes; }
         }
 
@@ -86,7 +83,7 @@
         }
     }
 
-    public sealed class UrlRelation : RelationBase<string>
+    public sealed class UrlRelation : RelationBase<Uri>
     {
         internal UrlRelation(string type,
                              string target,
@@ -94,7 +91,7 @@
                              string begin,
                              string end,
                              string [] attributes)
-            : base (type, target, direction, begin, end, attributes)
+            : base (type, new Uri (target), direction, begin, end, attributes)
         {
         }
     }

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Release.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Release.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Release.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // Release.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -52,11 +48,7 @@
         
         #region Constructors
 
-        Release (string mbid) : base (mbid, null)
-        {
-        }
-
-        Release (string mbid, string parameters) : base (mbid, parameters)
+        Release (string id) : base (id)
         {
         }
 
@@ -66,15 +58,15 @@
         
         #endregion
         
-        #region Protected Overrides
+        #region Protected
         
-        protected override string UrlExtension {
+        internal override string UrlExtension {
             get { return EXTENSION; }
         }
         
         static readonly string [] track_params = new string [] { "tracks", "track-level-rels", "artist" };
         
-        protected override void CreateIncCore (StringBuilder builder)
+        internal override void CreateIncCore (StringBuilder builder)
         {
             AppendIncParameters (builder, "release-events", "labels");
             if (discs == null) AppendIncParameters (builder, "discs");
@@ -85,95 +77,86 @@
             base.CreateIncCore (builder);
         }
 
-        protected override void LoadMissingDataCore ()
+        internal override void LoadMissingDataCore ()
         {
-            Release release = new Release (Id, CreateInc ());
-            type = release.Type;
-            status = release.Status;
-            language = release.Language;
-            script = release.Script;
-            asin = release.Asin;
-            events = release.Events;
-            if (discs == null) discs = release.Discs;
-            if (tracks == null) tracks = release.Tracks;
+            Release release = new Release (Id);
+            type = release.GetReleaseType ();
+            status = release.GetReleaseStatus ();
+            language = release.GetLanguage ();
+            script = release.GetScript ();
+            asin = release.GetAsin ();
+            events = release.GetEvents ();
+            if (discs == null) discs = release.GetDiscs ();
+            if (tracks == null) tracks = release.GetTracks ();
             base.LoadMissingDataCore (release);
         }
 
-        protected override bool ProcessAttributes (XmlReader reader)
+        internal override void ProcessAttributes (XmlReader reader)
         {
             // How sure am I about getting the type and status in the "Type Status" format?
             // MB really ought to specify these two things seperatly.
-            string type_string = reader ["type"];
-            if (type_string != null)
-                foreach (string token in type_string.Split (' ')) {
-                    if (type == null) {
-                        type = Utils.StringToEnumOrNull<ReleaseType> (token);
-                        if (type != null) continue;
-                    }
-                    this.status = Utils.StringToEnumOrNull<ReleaseStatus> (token);
-                }
-            return this.type != null || this.status != null;
-        }
-
-        protected override bool ProcessXml (XmlReader reader)
-        {
-            reader.Read ();
-            bool result = base.ProcessXml (reader);
-            if (!result) {
-                result = true;
-                switch (reader.Name) {
-                case "text-representation":
-                    language = reader ["language"];
-                    script = reader ["script"];
-                    break;
-                case "asin":
-                    reader.Read ();
-                    if (reader.NodeType == XmlNodeType.Text)
-                        asin = reader.ReadContentAsString ();
-                    break;
-                case "disc-list": {
-                    if (reader.ReadToDescendant ("disc")) {
-                        List<Disc> discs = new List<Disc> ();
-                        do discs.Add (new Disc (reader.ReadSubtree ()));
-                        while (reader.ReadToNextSibling ("disc"));
-                        this.discs = discs.AsReadOnly ();
-                    }
-                    break;
-                }
-                case "release-event-list":
-                    if (!AllDataLoaded) reader.Skip(); // FIXME this is a workaround for Mono bug 334752
-                    if (reader.ReadToDescendant ("event")) {
-                        List<Event> events = new List<Event> ();
-                        do events.Add (new Event (reader.ReadSubtree ()));
-                        while (reader.ReadToNextSibling ("event"));
-                        this.events = events.AsReadOnly ();
-                    }
-                    break;
-                case "track-list": {
-                    string offset = reader ["offset"];
-                    if (offset != null)
-                        track_number = int.Parse (offset) + 1;
-                    if (reader.ReadToDescendant ("track")) {
-                        List<Track> tracks = new List<Track> ();
-                        do tracks.Add (new Track (reader.ReadSubtree (), Artist, AllDataLoaded));
-                        while (reader.ReadToNextSibling ("track"));
-                        this.tracks = tracks.AsReadOnly ();
-                    }
-                    break;
-                }
-                default:
-                    reader.Skip (); // FIXME this is a workaround for Mono bug 334752
-                    result = false;
-                    break;
-                }
+            string type_string = reader ["type"];
+            if (type_string != null) {
+                foreach (string token in type_string.Split (' ')) {
+                    if (type == null) {
+                        type = Utils.StringToEnumOrNull<ReleaseType> (token);
+                        if (type != null) continue;
+                    }
+                    this.status = Utils.StringToEnumOrNull<ReleaseStatus> (token);
+                }
             }
-            reader.Close ();
-            return result;
+        }
+
+        internal override void ProcessXmlCore (XmlReader reader)
+        {
+            switch (reader.Name) {
+            case "text-representation":
+                language = reader["language"];
+                script = reader["script"];
+                break;
+            case "asin":
+                asin = reader.ReadString ();
+                break;
+            case "disc-list":
+                if (reader.ReadToDescendant ("disc")) {
+                    List<Disc> discs = new List<Disc> ();
+                    do discs.Add (new Disc (reader.ReadSubtree ()));
+                    while (reader.ReadToNextSibling ("disc"));
+                    this.discs = discs.AsReadOnly ();
+                }
+                break;
+            case "release-event-list":
+                if (!AllDataLoaded) {
+                    reader.Skip (); // FIXME this is a workaround for Mono bug 334752
+                    return;
+                }
+                if (reader.ReadToDescendant ("event")) {
+                    List<Event> events = new List<Event> ();
+                    do events.Add (new Event (reader.ReadSubtree ()));
+                    while (reader.ReadToNextSibling ("event"));
+                    this.events = events.AsReadOnly ();
+                }
+                break;
+            case "track-list":
+                string offset = reader["offset"];
+                if (offset != null)
+                    track_number = int.Parse (offset) + 1;
+                if (reader.ReadToDescendant ("track")) {
+                    List<Track> tracks = new List<Track> ();
+                    do tracks.Add (new Track (reader.ReadSubtree (), GetArtist (), AllDataLoaded));
+                    while (reader.ReadToNextSibling ("track"));
+                    this.tracks = tracks.AsReadOnly ();
+                }
+                break;
+            default:
+                base.ProcessXmlCore (reader);
+                break;
+            }
         }
         
         #endregion
 
-        #region Properties
+        #region Public
 
         [Queryable ("reid")]
         public override string Id {
@@ -181,46 +164,55 @@
         }
 
         [Queryable ("release")]
-        public override string Title {
-            get { return base.Title; }
+        public override string GetTitle ()
+        { 
+            return base.GetTitle ();
         }
 
-        [Queryable]
-        public ReleaseType Type {
-            get { return GetPropertyOrDefault (ref type, ReleaseType.None); }
+        [Queryable ("type")]
+        public ReleaseType GetReleaseType ()
+        {
+            return GetPropertyOrDefault (ref type, ReleaseType.None);
         }
 
-        [Queryable]
-        public ReleaseStatus Status {
-            get { return GetPropertyOrDefault (ref status, ReleaseStatus.None); }
+        [Queryable ("status")]
+        public ReleaseStatus GetReleaseStatus ()
+        {
+            return GetPropertyOrDefault (ref status, ReleaseStatus.None);
         }
 
-        public string Language {
-            get { return GetPropertyOrNull (ref language); }
+        public string GetLanguage ()
+        {
+            return GetPropertyOrNull (ref language);
         }
 
-        [Queryable]
-        public string Script {
-            get { return GetPropertyOrNull (ref script); }
+        [Queryable ("script")]
+        public string GetScript ()
+        {
+            return GetPropertyOrNull (ref script);
         }
 
-        [Queryable]
-        public string Asin {
-            get { return GetPropertyOrNull (ref asin); }
+        [Queryable ("asin")]
+        public string GetAsin ()
+        {
+            return GetPropertyOrNull (ref asin);
         }
 
         [QueryableMember("Count", "discids")]
-        public ReadOnlyCollection<Disc> Discs {
-            get { return GetPropertyOrNew (ref discs); }
+        public ReadOnlyCollection<Disc> GetDiscs ()
+        { 
+            return GetPropertyOrNew (ref discs);
         }
 
-        public ReadOnlyCollection<Event> Events {
-            get { return GetPropertyOrNew (ref events); }
+        public ReadOnlyCollection<Event> GetEvents ()
+        {
+            return GetPropertyOrNew (ref events);
         }
 
         [QueryableMember ("Count", "tracks")]
-        public ReadOnlyCollection<Track> Tracks {
-            get { return GetPropertyOrNew (ref tracks); }
+        public ReadOnlyCollection<Track> GetTracks ()
+        {
+            return GetPropertyOrNew (ref tracks);
         }
 
         internal int TrackNumber {
@@ -231,10 +223,10 @@
         
         #region Static
 
-        public static Release Get (string mbid)
+        public static Release Get (string id)
         {
-            if (mbid == null) throw new ArgumentNullException ("mbid");
-            return new Release (mbid);
+            if (id == null) throw new ArgumentNullException ("id");
+            return new Release (id);
         }
 
         public static Query<Release> Query (string title)
@@ -269,7 +261,7 @@
         public static Query<Release> Query (ReleaseQueryParameters parameters)
         {
             if (parameters == null) throw new ArgumentNullException ("parameters");
-            return new Query<Release> (EXTENSION, QueryLimit, parameters.ToString ());
+            return new Query<Release> (EXTENSION, parameters.ToString ());
         }
 
         public static Query<Release> QueryFromDevice(string device)
@@ -284,7 +276,7 @@
         public static Query<Release> QueryLucene (string luceneQuery)
         {
             if (luceneQuery == null) throw new ArgumentNullException ("luceneQuery");
-            return new Query<Release> (EXTENSION, QueryLimit, CreateLuceneParameter (luceneQuery));
+            return new Query<Release> (EXTENSION, CreateLuceneParameter (luceneQuery));
         }
 
         public static implicit operator string (Release release)
@@ -373,9 +365,8 @@
             set { script = value; }
         }
 
-        public override string ToString ()
+        internal override void ToStringCore (StringBuilder builder)
         {
-            StringBuilder builder = new StringBuilder ();
             if (disc_id != null) {
                 builder.Append ("&discid=");
                 builder.Append (disc_id);
@@ -396,8 +387,6 @@
                 builder.Append ("&script=");
                 builder.Append (script);
             }
-            AppendBaseToBuilder (builder);
-            return builder.ToString ();
         }
     }
     

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Track.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Track.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Track.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // Track.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -38,7 +34,7 @@
         #region Private
         
         const string EXTENSION = "track";
-        uint duration;
+        TimeSpan? duration;
         ReadOnlyCollection<Release> releases;
         ReadOnlyCollection<string> puids;
         
@@ -46,11 +42,7 @@
         
         #region Constructors
 
-        Track (string mbid) : base (mbid, null)
-        {
-        }
-
-        Track (string mbid, string parameters) : base (mbid, parameters)
+        Track (string id) : base (id)
         {
         }
 
@@ -64,74 +56,59 @@
         
         #endregion
 
-        #region Protected Overrides
+        #region Protected
         
-        protected override string UrlExtension {
+        internal override string UrlExtension {
             get { return EXTENSION; }
         }
         
-        protected override void CreateIncCore (StringBuilder builder)
+        internal override void CreateIncCore (StringBuilder builder)
         {
             if (releases == null) AppendIncParameters (builder, "releases");
             if (puids == null) AppendIncParameters (builder, "puids");
             base.CreateIncCore (builder);
         }
 
-        protected override void LoadMissingDataCore ()
+        internal override void LoadMissingDataCore ()
         {
-            Track track = new Track (Id, CreateInc ());
-            duration = track.Duration;
-            if (releases == null) releases = track.Releases;
-            if (puids == null) puids = track.Puids;
+            Track track = new Track (Id);
+            duration = track.GetDuration ();
+            if (releases == null) releases = track.GetReleases ();
+            if (puids == null) puids = track.GetPuids ();
             base.LoadMissingDataCore (track);
-        }
-
-        protected override bool ProcessAttributes (XmlReader reader)
-        {
-            return true;
-        }
-
-        protected override bool ProcessXml (XmlReader reader)
-        {
-            reader.Read ();
-            bool result = base.ProcessXml (reader);
-            if (!result) {
-                result = true;
-                switch (reader.Name) {
-                case "duration":
-                    reader.Read ();
-                    if (reader.NodeType == XmlNodeType.Text)
-                        duration = uint.Parse (reader.ReadContentAsString ());
-                    break;
-                case "release-list":
-                    if(reader.ReadToDescendant ("release")) {
-                        List<Release> releases = new List<Release> ();
-                        do releases.Add (new Release (reader.ReadSubtree ()));
-                        while (reader.ReadToNextSibling ("release"));
-                        this.releases = releases.AsReadOnly ();
-                    }
-                    break;
-                case "puid-list":
-                    if(reader.ReadToDescendant ("puid")) {
-                        List<string> puids = new List<string> ();
-                        do puids.Add (reader ["id"]);
-                        while (reader.ReadToNextSibling ("puid"));
-                        this.puids = puids.AsReadOnly ();
-                    }
-                    break;
-                default:
-                    reader.Skip (); // FIXME this is a workaround for Mono bug 334752
-                    result = false;
-                    break;
-                }
-            }
-            reader.Close ();
-            return result;
+        }
+
+        internal override void ProcessXmlCore (XmlReader reader)
+        {
+            switch (reader.Name) {
+            case "duration":
+                duration = TimeSpan.FromMilliseconds (reader.ReadElementContentAsDouble ());
+                break;
+            case "release-list":
+                if (reader.ReadToDescendant ("release")) {
+                    List<Release> releases = new List<Release> ();
+                    do releases.Add (new Release (reader.ReadSubtree ()));
+                    while (reader.ReadToNextSibling ("release"));
+                    this.releases = releases.AsReadOnly ();
+                }
+                break;
+            case "puid-list":
+                if (reader.ReadToDescendant ("puid")) {
+                    List<string> puids = new List<string> ();
+                    do puids.Add (reader["id"]);
+                    while (reader.ReadToNextSibling ("puid"));
+                    this.puids = puids.AsReadOnly ();
+                }
+                break;
+            default:
+                base.ProcessXmlCore (reader);
+                break;
+            }
         }
         
         #endregion
 
-        #region Properties
+        #region Public
 
         [Queryable ("trid")]
         public override string Id {
@@ -139,30 +116,33 @@
         }
 
         [Queryable ("track")]
-        public override string Title {
-            get { return base.Title; }
+        public override string GetTitle ()
+        {
+            return base.GetTitle ();
         }
 
         [Queryable ("dur")]
-        public uint Duration {
-            get { return duration; }
+        public TimeSpan GetDuration ()
+        {
+            return GetPropertyOrDefault (ref duration);
         }
 
         [QueryableMember ("Contains", "release")]
-        public ReadOnlyCollection<Release> Releases {
-            get { return GetPropertyOrNew (ref releases); }
-
+        public ReadOnlyCollection<Release> GetReleases ()
+        {
+            return GetPropertyOrNew (ref releases);
         }
 
-        public ReadOnlyCollection<string> Puids {
-            get { return GetPropertyOrNew (ref puids); }
+        public ReadOnlyCollection<string> GetPuids ()
+        {
+            return GetPropertyOrNew (ref puids);
         }
 
         public int GetTrackNumber (Release release)
         {
             if (release == null) throw new ArgumentNullException ("release");
             
-            foreach (Release r in Releases)
+            foreach (Release r in GetReleases ())
                 if (r.Equals (release))
                     return r.TrackNumber;
             return -1;
@@ -172,10 +152,10 @@
         
         #region Static
 
-        public static Track Get (string mbid)
+        public static Track Get (string id)
         {
-            if (mbid == null) throw new ArgumentNullException ("mbid");
-            return new Track (mbid);
+            if (id == null) throw new ArgumentNullException ("id");
+            return new Track (id);
         }
 
         public static Query<Track> Query (string title)
@@ -187,40 +167,40 @@
             return Query (parameters);
         }
 
-        public static Query<Track> Query (string title, string release)
+        public static Query<Track> Query (string title, string artist)
         {
             if (title == null) throw new ArgumentNullException ("title");
-            if (release == null) throw new ArgumentNullException ("release");
+            if (artist == null) throw new ArgumentNullException ("artist");
             
             TrackQueryParameters parameters = new TrackQueryParameters ();
             parameters.Title = title;
-            parameters.Release = release;
+            parameters.Artist = artist;
             return Query (parameters);
         }
         
-        public static Query<Track> Query (string title, string release, string artist)
+        public static Query<Track> Query (string title, string artist, string release)
         {
             if (title == null) throw new ArgumentNullException ("title");
-            if (release == null) throw new ArgumentNullException ("release");
             if (artist == null) throw new ArgumentNullException ("artist");
+            if (release == null) throw new ArgumentNullException ("release");
             
             TrackQueryParameters parameters = new TrackQueryParameters ();
             parameters.Title = title;
-            parameters.Release = release;
             parameters.Artist = artist;
+            parameters.Release = release;
             return Query (parameters);
         }
 
         public static Query<Track> Query (TrackQueryParameters parameters)
         {
             if (parameters == null) throw new ArgumentNullException ("parameters");
-            return new Query<Track> (EXTENSION, QueryLimit, parameters.ToString ());
+            return new Query<Track> (EXTENSION, parameters.ToString ());
         }
 
         public static Query<Track> QueryLucene (string luceneQuery)
         {
             if(luceneQuery == null) throw new ArgumentNullException ("luceneQuery"); 
-            return new Query<Track> (EXTENSION, QueryLimit, CreateLuceneParameter (luceneQuery));
+            return new Query<Track> (EXTENSION, CreateLuceneParameter (luceneQuery));
         }
 
         public static implicit operator string (Track track)
@@ -266,9 +246,8 @@
             set { puid = value; }
         }
 
-        public override string ToString ()
+        internal override void ToStringCore (StringBuilder builder)
         {
-            StringBuilder builder = new StringBuilder ();
             if (release != null) {
                 builder.Append ("&release=");
                 Utils.PercentEncode (builder, release);
@@ -289,8 +268,6 @@
                 builder.Append ("&puid=");
                 builder.Append (puid);
             }
-            AppendBaseToBuilder (builder);
-            return builder.ToString ();
         }
     }
     

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Utils.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Utils.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/Utils.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // Utils.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,8 +20,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 using System.Text;
 
@@ -63,13 +59,6 @@
             return null;
         }
         
-        public static string PercentEncode (string value)
-        {
-            StringBuilder builder = new StringBuilder ();
-            PercentEncode (builder, value);
-            return builder.ToString ();
-        }
-        
         public static void PercentEncode (StringBuilder builder, string value)
         {
             foreach (char c in value) {
@@ -79,7 +68,7 @@
                 else {
                     builder.Append ('%');
                     foreach (byte b in Encoding.UTF8.GetBytes (new char [] { c }))
-                        builder.Append (string.Format ("{0:X}", b));
+                        builder.AppendFormat ("{0:X}", b);
                 } 
             }
         }

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/XmlRequestEventArgs.cs
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/XmlRequestEventArgs.cs	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/XmlRequestEventArgs.cs	Thu Apr  2 20:28:54 2009
@@ -1,5 +1,3 @@
-#region License
-
 // XmlRequestEventArgs.cs
 //
 // Copyright (c) 2008 Scott Peterson <lunchtimemama gmail com>
@@ -22,18 +20,16 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#endregion
-
 using System;
 
 namespace MusicBrainz
 {
     public sealed class XmlRequestEventArgs : EventArgs
     {
-        public readonly string Uri;
+        public readonly Uri Uri;
         public readonly bool FromCache;
         
-        public XmlRequestEventArgs (string uri, bool fromCache)
+        internal XmlRequestEventArgs (Uri uri, bool fromCache)
         {
             Uri = uri;
             FromCache = fromCache;

Modified: trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/sync.sh
==============================================================================
--- trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/sync.sh	(original)
+++ trunk/banshee/src/Libraries/MusicBrainz/MusicBrainz/sync.sh	Thu Apr  2 20:28:54 2009
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 rm -f *.cs
-svn co svn://svn.gnome.org/svn/banshee/trunk/musicbrainz-sharp/src/MusicBrainz/MusicBrainz
+svn co http://svn.musicbrainz.org/musicbrainz-sharp/trunk/src/MusicBrainz/MusicBrainz
 cp MusicBrainz/*.cs .
 rm -rf MusicBrainz
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]